home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / cvs-1.8 / cvs-1 / cvs-1.8.1 / src / client.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-06  |  108.1 KB  |  4,491 lines

  1. /* CVS client-related stuff.  */
  2.  
  3. #ifdef HAVE_CONFIG_H
  4. #include "config.h"
  5. #endif /* HAVE_CONFIG_H */
  6.  
  7. #include "cvs.h"
  8. #include "getline.h"
  9. #include "edit.h"
  10.  
  11. #ifdef CLIENT_SUPPORT
  12.  
  13. #include "md5.h"
  14.  
  15. #if defined(AUTH_CLIENT_SUPPORT) || HAVE_KERBEROS || USE_DIRECT_TCP
  16. #  ifdef HAVE_WINSOCK_H
  17. #    include <winsock.h>
  18. #  else /* No winsock.h */
  19. #    include <sys/socket.h>
  20. #    include <netinet/in.h>
  21. #    include <netdb.h>
  22. #  endif /* No winsock.h */
  23. #endif /* defined(AUTH_CLIENT_SUPPORT) || HAVE_KERBEROS || USE_DIRECT_TCP */
  24.  
  25. #ifdef AUTH_CLIENT_SUPPORT
  26. char *get_cvs_password PROTO((char *user, char *host, char *cvsrooot));
  27. #endif /* AUTH_CLIENT_SUPPORT */
  28.  
  29. #if HAVE_KERBEROS || USE_DIRECT_TCP
  30. #define CVS_PORT 1999
  31.  
  32. #if HAVE_KERBEROS
  33. #include <krb.h>
  34.  
  35. extern char *krb_realmofhost ();
  36. #ifndef HAVE_KRB_GET_ERR_TEXT
  37. #define krb_get_err_text(status) krb_err_txt[status]
  38. #endif /* HAVE_KRB_GET_ERR_TEXT */
  39. #endif /* HAVE_KERBEROS */
  40.  
  41. #endif /* HAVE_KERBEROS || USE_DIRECT_TCP */
  42.  
  43. static void add_prune_candidate PROTO((char *));
  44.  
  45. /* All the commands.  */
  46. int add PROTO((int argc, char **argv));
  47. int admin PROTO((int argc, char **argv));
  48. int checkout PROTO((int argc, char **argv));
  49. int commit PROTO((int argc, char **argv));
  50. int diff PROTO((int argc, char **argv));
  51. int history PROTO((int argc, char **argv));
  52. int import PROTO((int argc, char **argv));
  53. int cvslog PROTO((int argc, char **argv));
  54. int patch PROTO((int argc, char **argv));
  55. int release PROTO((int argc, char **argv));
  56. int cvsremove PROTO((int argc, char **argv));
  57. int rtag PROTO((int argc, char **argv));
  58. int status PROTO((int argc, char **argv));
  59. int tag PROTO((int argc, char **argv));
  60. int update PROTO((int argc, char **argv));
  61.  
  62. /* All the response handling functions.  */
  63. static void handle_ok PROTO((char *, int));
  64. static void handle_error PROTO((char *, int));
  65. static void handle_valid_requests PROTO((char *, int));
  66. static void handle_checked_in PROTO((char *, int));
  67. static void handle_new_entry PROTO((char *, int));
  68. static void handle_checksum PROTO((char *, int));
  69. static void handle_copy_file PROTO((char *, int));
  70. static void handle_updated PROTO((char *, int));
  71. static void handle_merged PROTO((char *, int));
  72. static void handle_patched PROTO((char *, int));
  73. static void handle_removed PROTO((char *, int));
  74. static void handle_remove_entry PROTO((char *, int));
  75. static void handle_set_static_directory PROTO((char *, int));
  76. static void handle_clear_static_directory PROTO((char *, int));
  77. static void handle_set_sticky PROTO((char *, int));
  78. static void handle_clear_sticky PROTO((char *, int));
  79. static void handle_set_checkin_prog PROTO((char *, int));
  80. static void handle_set_update_prog PROTO((char *, int));
  81. static void handle_module_expansion PROTO((char *, int));
  82. static void handle_m PROTO((char *, int));
  83. static void handle_e PROTO((char *, int));
  84. static void handle_notified PROTO((char *, int));
  85.  
  86. static size_t try_read_from_server PROTO ((char *, size_t));
  87. #endif /* CLIENT_SUPPORT */
  88.  
  89. #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
  90.  
  91. /* Shared with server.  */
  92.  
  93. /*
  94.  * Return a malloc'd, '\0'-terminated string
  95.  * corresponding to the mode in SB.
  96.  */
  97. char *
  98. #ifdef __STDC__
  99. mode_to_string (mode_t mode)
  100. #else /* ! __STDC__ */
  101. mode_to_string (mode)
  102.     mode_t mode;
  103. #endif /* __STDC__ */
  104. {
  105.     char buf[18], u[4], g[4], o[4];
  106.     int i;
  107.  
  108.     i = 0;
  109.     if (mode & S_IRUSR) u[i++] = 'r';
  110.     if (mode & S_IWUSR) u[i++] = 'w';
  111.     if (mode & S_IXUSR) u[i++] = 'x';
  112.     u[i] = '\0';
  113.     
  114.     i = 0;
  115.     if (mode & S_IRGRP) g[i++] = 'r';
  116.     if (mode & S_IWGRP) g[i++] = 'w';
  117.     if (mode & S_IXGRP) g[i++] = 'x';
  118.     g[i] = '\0';
  119.     
  120.     i = 0;
  121.     if (mode & S_IROTH) o[i++] = 'r';
  122.     if (mode & S_IWOTH) o[i++] = 'w';
  123.     if (mode & S_IXOTH) o[i++] = 'x';
  124.     o[i] = '\0';
  125.  
  126.     sprintf(buf, "u=%s,g=%s,o=%s", u, g, o);
  127.     return xstrdup(buf);
  128. }
  129.  
  130. /*
  131.  * Change mode of FILENAME to MODE_STRING.
  132.  * Returns 0 for success or errno code.
  133.  */
  134. int
  135. change_mode (filename, mode_string)
  136.     char *filename;
  137.     char *mode_string;
  138. {
  139. #ifdef CHMOD_BROKEN
  140.     char *p;
  141.     int writeable = 0;
  142.  
  143.     /* We can only distinguish between
  144.          1) readable
  145.          2) writeable
  146.          3) Picasso's "Blue Period"
  147.        We handle the first two. */
  148.     p = mode_string;
  149.     while (*p != '\0')
  150.     {
  151.     if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
  152.     {
  153.         char *q = p + 2;
  154.         while (*q != ',' && *q != '\0')
  155.         {
  156.         if (*q == 'w')
  157.             writeable = 1;
  158.         ++q;
  159.         }
  160.     }
  161.     /* Skip to the next field.  */
  162.     while (*p != ',' && *p != '\0')
  163.         ++p;
  164.     if (*p == ',')
  165.         ++p;
  166.     }
  167.  
  168.     xchmod (filename, writeable);
  169.     return 0;
  170.  
  171. #else /* ! CHMOD_BROKEN */
  172.  
  173.     char *p;
  174.     mode_t mode = 0;
  175.  
  176.     p = mode_string;
  177.     while (*p != '\0')
  178.     {
  179.     if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
  180.     {
  181.         int can_read = 0, can_write = 0, can_execute = 0;
  182.         char *q = p + 2;
  183.         while (*q != ',' && *q != '\0')
  184.         {
  185.         if (*q == 'r')
  186.             can_read = 1;
  187.         else if (*q == 'w')
  188.             can_write = 1;
  189.         else if (*q == 'x')
  190.             can_execute = 1;
  191.         ++q;
  192.         }
  193.         if (p[0] == 'u')
  194.         {
  195.         if (can_read)
  196.             mode |= S_IRUSR;
  197.         if (can_write)
  198.             mode |= S_IWUSR;
  199.         if (can_execute)
  200.             mode |= S_IXUSR;
  201.         }
  202.         else if (p[0] == 'g')
  203.         {
  204.         if (can_read)
  205.             mode |= S_IRGRP;
  206.         if (can_write)
  207.             mode |= S_IWGRP;
  208.         if (can_execute)
  209.             mode |= S_IXGRP;
  210.         }
  211.         else if (p[0] == 'o')
  212.         {
  213.         if (can_read)
  214.             mode |= S_IROTH;
  215.         if (can_write)
  216.             mode |= S_IWOTH;
  217.         if (can_execute)
  218.             mode |= S_IXOTH;
  219.         }
  220.     }
  221.     /* Skip to the next field.  */
  222.     while (*p != ',' && *p != '\0')
  223.         ++p;
  224.     if (*p == ',')
  225.         ++p;
  226.     }
  227.  
  228.     if (chmod (filename, mode) < 0)
  229.     return errno;
  230.     return 0;
  231. #endif /* ! CHMOD_BROKEN */
  232. }
  233.  
  234. #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
  235.  
  236. #ifdef CLIENT_SUPPORT
  237.  
  238. /* The host part of CVSROOT.  */
  239. static char *server_host;
  240. /* The user part of CVSROOT */
  241. static char *server_user;
  242. /* The repository part of CVSROOT.  */
  243. static char *server_cvsroot;
  244.  
  245. int client_active;
  246.  
  247. int client_prune_dirs;
  248.  
  249. static int cvsroot_parsed = 0;
  250.  
  251. static List *ignlist = (List *) NULL;
  252.  
  253. /* Set server_host and server_cvsroot.  */
  254. static void
  255. parse_cvsroot ()
  256. {
  257.     char *p;
  258. #ifdef AUTH_CLIENT_SUPPORT
  259.     static char *access_method;
  260. #endif /* AUTH_CLIENT_SUPPORT */
  261.  
  262.     /* Don't go through the trouble twice. */
  263.     if (cvsroot_parsed)
  264.       return;
  265.  
  266.     server_host = xstrdup (CVSroot);
  267.  
  268. #ifdef AUTH_CLIENT_SUPPORT
  269.     if ((server_host[0] == ':'))
  270.     {
  271.       /* Access method specified, as in
  272.        * "cvs -d :pserver:user@host:/path".
  273.        * We need to get past that part of CVSroot before parsing the
  274.        * rest of it.
  275.        */
  276.       access_method = p = &(server_host[1]);
  277.  
  278.       if (! *access_method)
  279.         error (1, 0, "bad CVSroot: %s", CVSroot);
  280.  
  281.       if (! *(p = strchr (access_method, ':')))
  282.         error (1, 0, "bad CVSroot: %s", CVSroot);
  283.       
  284.       *p = '\0';
  285.       p++;
  286.  
  287.       server_host = p;
  288.       
  289.       if (! *server_host)
  290.         error (1, 0, "bad CVSroot: %s", CVSroot);
  291.  
  292.       if (strcmp (access_method, "pserver") == 0)
  293.         use_authenticating_server = 1;
  294.       else
  295.         error (1, 0, "unknown access method: %s", access_method);
  296.     }
  297. #endif /* AUTH_CLIENT_SUPPORT */
  298.     
  299.     /* First get just the pathname. */
  300.     server_cvsroot = strchr (server_host, ':');
  301.     *server_cvsroot = '\0';
  302.     ++server_cvsroot;
  303.     
  304.     /* Then deal with host and possible user. */
  305.     if ( (p = strchr (server_host, '@')) == NULL)
  306.     {
  307.       server_user = NULL;
  308.     }
  309.     else
  310.     {
  311.       server_user = server_host;
  312.       server_host = p;
  313.       ++server_host;
  314.       *p = '\0';
  315.     }
  316.              
  317.     client_active = 1;
  318.     cvsroot_parsed = 1;
  319. }
  320.  
  321. #ifdef NO_SOCKET_TO_FD
  322. /* Under certain circumstances, we must communicate with the server
  323.    via a socket using send() and recv().  This is because under some
  324.    operating systems (OS/2 and Windows 95 come to mind), a socket
  325.    cannot be converted to a file descriptor -- it must be treated as a
  326.    socket and nothing else. */
  327. static int use_socket_style = 0;
  328. static int server_sock;
  329. #endif /* NO_SOCKET_TO_FD */
  330.  
  331. /* Stream to write to the server.  */
  332. static FILE *to_server;
  333. /* Stream to read from the server.  */
  334. static FILE *from_server;
  335.  
  336. /* We might want to log client/server traffic. */
  337. static FILE *from_server_logfile;
  338. static FILE *to_server_logfile;
  339.  
  340. #if ! RSH_NOT_TRANSPARENT
  341. /* Process ID of rsh subprocess.  */
  342. static int rsh_pid = -1;
  343. #endif /* ! RSH_NOT_TRANSPARENT */
  344.  
  345.  
  346. /*
  347.  * Read a line from the server.  Result does not include the terminating \n.
  348.  *
  349.  * Space for the result is malloc'd and should be freed by the caller.
  350.  *
  351.  * Returns number of bytes read.  If EOF_OK, then return 0 on end of file,
  352.  * else end of file is an error.
  353.  */
  354. static int
  355. read_line (resultp, eof_ok)
  356.     char **resultp;
  357.     int eof_ok;
  358. {
  359.     int c;
  360.     char *result;
  361.     size_t input_index = 0;
  362.     size_t result_size = 80;
  363.  
  364. #ifdef NO_SOCKET_TO_FD
  365.     if (! use_socket_style)
  366. #endif /* NO_SOCKET_TO_FD */
  367.       fflush (to_server);
  368.  
  369.     result = (char *) xmalloc (result_size);
  370.  
  371.     while (1)
  372.     {
  373.  
  374. #ifdef NO_SOCKET_TO_FD
  375.       if (use_socket_style)
  376.         {
  377.           char ch;
  378.           /* Yes, this sucks performance-wise.  Short of implementing
  379.              our own buffering, I'm not sure how to effect a big
  380.              improvement.  We could at least avoid calling
  381.              read_from_server() for each character if we were willing
  382.              to duplicate a lot of its code, but I'm not sure that's
  383.              worth it. */
  384.           read_from_server (&ch, 1);
  385.           c = ch;
  386.         }
  387.       else
  388. #endif /* NO_SOCKET_TO_FD */
  389.         c = getc (from_server);
  390.  
  391.     if (c == EOF)
  392.     {
  393.         free (result);
  394.  
  395. #ifdef NO_SOCKET_TO_FD
  396.             if (! use_socket_style)
  397. #endif /* NO_SOCKET_TO_FD */
  398.               if (ferror (from_server))
  399.                 error (1, errno, "reading from server");
  400.             
  401.         /* It's end of file.  */
  402.         if (eof_ok)
  403.         return 0;
  404.         else
  405.         error (1, 0, "end of file from server (consult above messages if any)");
  406.     }
  407.  
  408.     if (c == '\n')
  409.         break;
  410.     
  411.     result[input_index++] = c;
  412.     while (input_index + 1 >= result_size)
  413.     {
  414.         result_size *= 2;
  415.         result = (char *) xrealloc (result, result_size);
  416.     }
  417.     }
  418.  
  419.     if (resultp)
  420.     *resultp = result;
  421.  
  422.     /* Terminate it just for kicks, but we *can* deal with embedded NULs.  */
  423.     result[input_index] = '\0';
  424.  
  425. #ifdef NO_SOCKET_TO_FD
  426.     if (! use_socket_style)
  427. #endif /* NO_SOCKET_TO_FD */
  428.     {
  429.     /*
  430.      * If we're using socket style, then everything has already
  431.      * been logged because read_from_server() was used to get the
  432.      * individual chars, and read_from_server() logs already.
  433.      */
  434.     if (from_server_logfile)
  435.     {
  436.         if (fwrite (result, 1, input_index, from_server_logfile)
  437.         < input_index)
  438.         error (0, errno, "writing to from-server logfile");
  439.         putc ('\n', from_server_logfile);
  440.     }
  441.     }
  442.     
  443.     if (resultp == NULL)
  444.     free (result);
  445.     return input_index;
  446. }
  447.  
  448. #endif /* CLIENT_SUPPORT */
  449.  
  450.  
  451. #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
  452.  
  453. /*
  454.  * Zero if compression isn't supported or requested; non-zero to indicate
  455.  * a compression level to request from gzip.
  456.  */
  457. int gzip_level;
  458.  
  459. int filter_through_gzip (fd, dir, level, pidp)
  460.      int fd, dir, level;
  461.      pid_t *pidp;
  462. {
  463.   static char buf[5] = "-";
  464.   static char *gzip_argv[3] = { "gzip", buf };
  465.  
  466.   sprintf (buf+1, "%d", level);
  467.   return filter_stream_through_program (fd, dir, &gzip_argv[0], pidp);
  468. }
  469.  
  470. int filter_through_gunzip (fd, dir, pidp)
  471.      int fd, dir;
  472.      pid_t *pidp;
  473. {
  474.   static char *gunzip_argv[3] = { "gunzip", "-d" };
  475.   return filter_stream_through_program (fd, dir, &gunzip_argv[0], pidp);
  476. }
  477.  
  478. #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
  479.  
  480. #ifdef CLIENT_SUPPORT
  481.  
  482. /*
  483.  * The Repository for the top level of this command (not necessarily
  484.  * the CVSROOT, just the current directory at the time we do it).
  485.  */
  486. static char *toplevel_repos;
  487.  
  488. /* Working directory when we first started.  */
  489. char toplevel_wd[PATH_MAX];
  490.  
  491. static void
  492. handle_ok (args, len)
  493.     char *args;
  494.     int len;
  495. {
  496.     return;
  497. }
  498.  
  499. static void
  500. handle_error (args, len)
  501.     char *args;
  502.     int len;
  503. {
  504.     int something_printed;
  505.     
  506.     /*
  507.      * First there is a symbolic error code followed by a space, which
  508.      * we ignore.
  509.      */
  510.     char *p = strchr (args, ' ');
  511.     if (p == NULL)
  512.     {
  513.     error (0, 0, "invalid data from cvs server");
  514.     return;
  515.     }
  516.     ++p;
  517.     len -= p - args;
  518.     something_printed = 0;
  519.     for (; len > 0; --len)
  520.     {
  521.     something_printed = 1;
  522.     putc (*p++, stderr);
  523.     }
  524.     if (something_printed)
  525.     putc ('\n', stderr);
  526. }
  527.  
  528. static void
  529. handle_valid_requests (args, len)
  530.     char *args;
  531.     int len;
  532. {
  533.     char *p = args;
  534.     char *q;
  535.     struct request *rq;
  536.     do
  537.     {
  538.     q = strchr (p, ' ');
  539.     if (q != NULL)
  540.         *q++ = '\0';
  541.     for (rq = requests; rq->name != NULL; ++rq)
  542.     {
  543.         if (strcmp (rq->name, p) == 0)
  544.         break;
  545.     }
  546.     if (rq->name == NULL)
  547.         /*
  548.          * It is a request we have never heard of (and thus never
  549.          * will want to use).  So don't worry about it.
  550.          */
  551.         ;
  552.     else
  553.     {
  554.         if (rq->status == rq_enableme)
  555.         {
  556.         /*
  557.          * Server wants to know if we have this, to enable the
  558.          * feature.
  559.          */
  560.         send_to_server (rq->name, 0);
  561.                 send_to_server ("\012", 0);
  562.  
  563.         if (!strcmp("UseUnchanged",rq->name))
  564.             use_unchanged = 1;
  565.         }
  566.         else
  567.         rq->status = rq_supported;
  568.     }
  569.     p = q;
  570.     } while (q != NULL);
  571.     for (rq = requests; rq->name != NULL; ++rq)
  572.     {
  573.     if (rq->status == rq_essential)
  574.         error (1, 0, "request `%s' not supported by server", rq->name);
  575.     else if (rq->status == rq_optional)
  576.         rq->status = rq_not_supported;
  577.     }
  578. }
  579.  
  580. static int use_directory = -1;
  581.  
  582. static char *get_short_pathname PROTO((const char *));
  583.  
  584. static char *
  585. get_short_pathname (name)
  586.     const char *name;
  587. {
  588.     const char *retval;
  589.     if (use_directory)
  590.     return (char *) name;
  591.     if (strncmp (name, toplevel_repos, strlen (toplevel_repos)) != 0)
  592.     error (1, 0, "server bug: name `%s' doesn't specify file in `%s'",
  593.            name, toplevel_repos);
  594.     retval = name + strlen (toplevel_repos) + 1;
  595.     if (retval[-1] != '/')
  596.     error (1, 0, "server bug: name `%s' doesn't specify file in `%s'",
  597.            name, toplevel_repos);
  598.     return (char *) retval;
  599. }
  600.  
  601. /*
  602.  * Do all the processing for PATHNAME, where pathname consists of the
  603.  * repository and the filename.  The parameters we pass to FUNC are:
  604.  * DATA is just the DATA parameter which was passed to
  605.  * call_in_directory; ENT_LIST is a pointer to an entries list (which
  606.  * we manage the storage for); SHORT_PATHNAME is the pathname of the
  607.  * file relative to the (overall) directory in which the command is
  608.  * taking place; and FILENAME is the filename portion only of
  609.  * SHORT_PATHNAME.  When we call FUNC, the curent directory points to
  610.  * the directory portion of SHORT_PATHNAME.  */
  611.  
  612. static char *last_dir_name;
  613.  
  614. static void
  615. call_in_directory (pathname, func, data)
  616.     char *pathname;
  617.     void (*func) PROTO((char *data, List *ent_list, char *short_pathname,
  618.               char *filename));
  619.     char *data;
  620. {
  621.     static List *last_entries;
  622.  
  623.     char *dir_name;
  624.     char *filename;
  625.     /* Just the part of pathname relative to toplevel_repos.  */
  626.     char *short_pathname = get_short_pathname (pathname);
  627.     char *p;
  628.  
  629.     /*
  630.      * Do the whole descent in parallel for the repositories, so we
  631.      * know what to put in CVS/Repository files.  I'm not sure the
  632.      * full hair is necessary since the server does a similar
  633.      * computation; I suspect that we only end up creating one
  634.      * directory at a time anyway.
  635.      *
  636.      * Also note that we must *only* worry about this stuff when we
  637.      * are creating directories; `cvs co foo/bar; cd foo/bar; cvs co
  638.      * CVSROOT; cvs update' is legitimate, but in this case
  639.      * foo/bar/CVSROOT/CVS/Repository is not a subdirectory of
  640.      * foo/bar/CVS/Repository.
  641.      */
  642.     char *reposname;
  643.     char *short_repos;
  644.     char *reposdirname;
  645.     char *rdirp;
  646.     int reposdirname_absolute;
  647.  
  648.     reposname = NULL;
  649.     if (use_directory)
  650.     read_line (&reposname, 0);
  651.  
  652.     reposdirname_absolute = 0;
  653.     if (reposname != NULL)
  654.     {
  655.     if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)) != 0)
  656.     {
  657.         reposdirname_absolute = 1;
  658.         short_repos = reposname;
  659.     }
  660.     else
  661.     {
  662.         short_repos = reposname + strlen (toplevel_repos) + 1;
  663.         if (short_repos[-1] != '/')
  664.         {
  665.         reposdirname_absolute = 1;
  666.         short_repos = reposname;
  667.         }
  668.     }
  669.     }
  670.     else
  671.     {
  672.     short_repos = short_pathname;
  673.     }
  674.     reposdirname = xstrdup (short_repos);
  675.     p = strrchr (reposdirname, '/');
  676.     if (p == NULL)
  677.     {
  678.     reposdirname = xrealloc (reposdirname, 2);
  679.     reposdirname[0] = '.'; reposdirname[1] = '\0';
  680.     }
  681.     else
  682.     *p = '\0';
  683.  
  684.     dir_name = xstrdup (short_pathname);
  685.     p = strrchr (dir_name, '/');
  686.     if (p == NULL)
  687.     {
  688.     dir_name = xrealloc (dir_name, 2);
  689.     dir_name[0] = '.'; dir_name[1] = '\0';
  690.     }
  691.     else
  692.     *p = '\0';
  693.     if (client_prune_dirs)
  694.     add_prune_candidate (dir_name);
  695.  
  696.     filename = strrchr (short_repos, '/');
  697.     if (filename == NULL)
  698.     filename = short_repos;
  699.     else
  700.     ++filename;
  701.  
  702.     if (reposname != NULL)
  703.     {
  704.     /* This is the use_directory case.  */
  705.  
  706.     short_pathname = xmalloc (strlen (pathname) + strlen (filename) + 5);
  707.     strcpy (short_pathname, pathname);
  708.     strcat (short_pathname, filename);
  709.     }
  710.  
  711.     if (last_dir_name == NULL
  712.     || strcmp (last_dir_name, dir_name) != 0)
  713.     {
  714.     if (last_dir_name)
  715.         free (last_dir_name);
  716.     last_dir_name = dir_name;
  717.  
  718.     if (toplevel_wd[0] == '\0')
  719.         if (getwd (toplevel_wd) == NULL)
  720.         error (1, 0,
  721.                "could not get working directory: %s", toplevel_wd);
  722.  
  723.     if (chdir (toplevel_wd) < 0)
  724.         error (1, errno, "could not chdir to %s", toplevel_wd);
  725.     if (chdir (dir_name) < 0)
  726.     {
  727.         char *dir;
  728.         char *dirp;
  729.         
  730.         if (! existence_error (errno))
  731.         error (1, errno, "could not chdir to %s", dir_name);
  732.         
  733.         /* Directory does not exist, we need to create it.  */
  734.         dir = xmalloc (strlen (dir_name) + 1);
  735.         dirp = dir_name;
  736.         rdirp = reposdirname;
  737.  
  738.         /* This algorithm makes nested directories one at a time
  739.                and create CVS administration files in them.  For
  740.                example, we're checking out foo/bar/baz from the
  741.                repository:
  742.  
  743.            1) create foo, point CVS/Repository to <root>/foo
  744.            2)     .. foo/bar                   .. <root>/foo/bar
  745.            3)     .. foo/bar/baz               .. <root>/foo/bar/baz
  746.            
  747.            As you can see, we're just stepping along DIR_NAME (with
  748.            DIRP) and REPOSDIRNAME (with RDIRP) respectively.
  749.  
  750.            We need to be careful when we are checking out a
  751.            module, however, since DIR_NAME and REPOSDIRNAME are not
  752.            going to be the same.  Since modules will not have any
  753.            slashes in their names, we should watch the output of
  754.            STRCHR to decide whether or not we should use STRCHR on
  755.            the RDIRP.  That is, if we're down to a module name,
  756.            don't keep picking apart the repository directory name.  */
  757.  
  758.         do
  759.         {
  760.         dirp = strchr (dirp, '/');
  761.         if (dirp)
  762.           {
  763.             strncpy (dir, dir_name, dirp - dir_name);
  764.             dir[dirp - dir_name] = '\0';
  765.             /* Skip the slash.  */
  766.             ++dirp;
  767.             if (rdirp == NULL)
  768.               error (0, 0,
  769.                  "internal error: repository string too short.");
  770.             else
  771.               rdirp = strchr (rdirp, '/');
  772.           }
  773.         else
  774.           {
  775.             /* If there are no more slashes in the dir name,
  776.                        we're down to the most nested directory -OR- to
  777.                        the name of a module.  In the first case, we
  778.                        should be down to a DIRP that has no slashes,
  779.                        so it won't help/hurt to do another STRCHR call
  780.                        on DIRP.  It will definitely hurt, however, if
  781.                        we're down to a module name, since a module
  782.                        name can point to a nested directory (that is,
  783.                        DIRP will still have slashes in it.  Therefore,
  784.                        we should set it to NULL so the routine below
  785.                        copies the contents of REMOTEDIRNAME onto the
  786.                        root repository directory (does this if rdirp
  787.                        is set to NULL, because we used to do an extra
  788.                        STRCHR call here). */
  789.  
  790.             rdirp = NULL;
  791.             strcpy (dir, dir_name);
  792.           }
  793.  
  794.         if (CVS_MKDIR (dir, 0777) < 0)
  795.         {
  796.                   /* Now, let me get this straight.  In IBM C/C++
  797.                    * under OS/2, the error string for EEXIST is:
  798.                    *
  799.                    *     "The file already exists",
  800.                    *
  801.                    * and the error string for EACCESS is:
  802.                    *
  803.                    *     "The file or directory specified is read-only".
  804.                    *
  805.                    * Nonetheless, mkdir() will set EACCESS if the
  806.                    * directory *exists*, according both to the
  807.                    * documentation and its actual behavior.
  808.                    *
  809.                    * I'm sure that this made sense, to someone,
  810.                    * somewhere, sometime.  Just not me, here, now.
  811.                    */
  812. #ifdef EACCESS
  813.                   if ((errno != EACCESS) && (errno != EEXIST))
  814.                     error (1, errno, "cannot make directory %s", dir);
  815. #else /* ! defined(EACCESS) */
  816.                   if ((errno != EEXIST))
  817.                     error (1, errno, "cannot make directory %s", dir);
  818. #endif /* defined(EACCESS) */
  819.                   
  820.                   /* It already existed, fine.  Just keep going.  */
  821.         }
  822.         else if (strcmp (command_name, "export") == 0)
  823.             /* Don't create CVSADM directories if this is export.  */
  824.             ;
  825.         else
  826.         {
  827.             /*
  828.              * Put repository in CVS/Repository.  For historical
  829.              * (pre-CVS/Root) reasons, this is an absolute pathname,
  830.              * but what really matters is the part of it which is
  831.              * relative to cvsroot.
  832.              */
  833.             char *repo;
  834.             char *r;
  835.  
  836.             repo = xmalloc (strlen (reposdirname)
  837.                     + strlen (toplevel_repos)
  838.                     + 80);
  839.             if (reposdirname_absolute)
  840.             r = repo;
  841.             else
  842.             {
  843.             strcpy (repo, toplevel_repos);
  844.             strcat (repo, "/");
  845.             r = repo + strlen (repo);
  846.             }
  847.  
  848.             if (rdirp)
  849.             {
  850.             strncpy (r, reposdirname, rdirp - reposdirname);
  851.             r[rdirp - reposdirname] = '\0';
  852.             }
  853.             else
  854.             strcpy (r, reposdirname);
  855.  
  856.             Create_Admin (dir, dir, repo,
  857.                   (char *)NULL, (char *)NULL);
  858.             free (repo);
  859.         }
  860.  
  861.         if (rdirp != NULL)
  862.         {
  863.             /* Skip the slash.  */
  864.             ++rdirp;
  865.         }
  866.  
  867.         } while (dirp != NULL);
  868.         free (dir);
  869.         /* Now it better work.  */
  870.         if (chdir (dir_name) < 0)
  871.         error (1, errno, "could not chdir to %s", dir_name);
  872.     }
  873.  
  874.     if (strcmp (command_name, "export") != 0)
  875.     {
  876.         if (last_entries)
  877.         Entries_Close (last_entries);
  878.         last_entries = Entries_Open (0);
  879.     }
  880.     }
  881.     else
  882.     free (dir_name);
  883.     free (reposdirname);
  884.     (*func) (data, last_entries, short_pathname, filename);
  885.     if (reposname != NULL)
  886.     {
  887.     free (short_pathname);
  888.     free (reposname);
  889.     }
  890. }
  891.  
  892. static void
  893. copy_a_file (data, ent_list, short_pathname, filename)
  894.     char *data;
  895.     List *ent_list;
  896.     char *short_pathname;
  897.     char *filename;
  898. {
  899.     char *newname;
  900. #ifdef USE_VMS_FILENAMES
  901.     char *p;
  902. #endif
  903.  
  904.     read_line (&newname, 0);
  905.  
  906. #ifdef USE_VMS_FILENAMES
  907.     /* Mogrify the filename so VMS is happy with it. */
  908.     for(p = newname; *p; p++)
  909.        if(*p == '.' || *p == '#') *p = '_';
  910. #endif
  911.  
  912.     copy_file (filename, newname);
  913.     free (newname);
  914. }
  915.  
  916. static void
  917. handle_copy_file (args, len)
  918.     char *args;
  919.     int len;
  920. {
  921.     call_in_directory (args, copy_a_file, (char *)NULL);
  922. }
  923.  
  924.  
  925. static void read_counted_file PROTO ((char *, char *));
  926.  
  927. /* Read from the server the count for the length of a file, then read
  928.    the contents of that file and write them to FILENAME.  FULLNAME is
  929.    the name of the file for use in error messages.  FIXME-someday:
  930.    extend this to deal with compressed files and make update_entries
  931.    use it.  On error, gives a fatal error.  */
  932. static void
  933. read_counted_file (filename, fullname)
  934.     char *filename;
  935.     char *fullname;
  936. {
  937.     char *size_string;
  938.     size_t size;
  939.     char *buf;
  940.  
  941.     /* Pointers in buf to the place to put data which will be read,
  942.        and the data which needs to be written, respectively.  */
  943.     char *pread;
  944.     char *pwrite;
  945.     /* Number of bytes left to read and number of bytes in buf waiting to
  946.        be written, respectively.  */
  947.     size_t nread;
  948.     size_t nwrite;
  949.  
  950.     FILE *fp;
  951.  
  952.     read_line (&size_string, 0);
  953.     if (size_string[0] == 'z')
  954.     error (1, 0, "\
  955. protocol error: compressed files not supported for that operation");
  956.     /* FIXME: should be doing more error checking, probably.  Like using
  957.        strtoul and making sure we used up the whole line.  */
  958.     size = atoi (size_string);
  959.     free (size_string);
  960.  
  961.     /* A more sophisticated implementation would use only a limited amount
  962.        of buffer space (8K perhaps), and read that much at a time.  We allocate
  963.        a buffer for the whole file only to make it easy to keep track what
  964.        needs to be read and written.  */
  965.     buf = xmalloc (size);
  966.  
  967.     /* FIXME-someday: caller should pass in a flag saying whether it
  968.        is binary or not.  I haven't carefully looked into whether
  969.        CVS/Template files should use local text file conventions or
  970.        not.  */
  971.     fp = fopen (filename, "wb");
  972.     if (fp == NULL)
  973.     error (1, errno, "cannot write %s", fullname);
  974.     nread = size;
  975.     nwrite = 0;
  976.     pread = buf;
  977.     pwrite = buf;
  978.     while (nread > 0 || nwrite > 0)
  979.     {
  980.     size_t n;
  981.  
  982.     if (nread > 0)
  983.     {
  984.         n = try_read_from_server (pread, nread);
  985.         nread -= n;
  986.         pread += n;
  987.         nwrite += n;
  988.     }
  989.  
  990.     if (nwrite > 0)
  991.     {
  992.         n = fwrite (pwrite, 1, nwrite, fp);
  993.         if (ferror (fp))
  994.         error (1, errno, "cannot write %s", fullname);
  995.         nwrite -= n;
  996.         pwrite += n;
  997.     }
  998.     }
  999.     free (buf);
  1000.     if (fclose (fp) < 0)
  1001.     error (1, errno, "cannot close %s", fullname);
  1002. }
  1003.  
  1004. /*
  1005.  * The Checksum response gives the checksum for the file transferred
  1006.  * over by the next Updated, Merged or Patch response.  We just store
  1007.  * it here, and then check it in update_entries.
  1008.  */
  1009.  
  1010. static int stored_checksum_valid;
  1011. static unsigned char stored_checksum[16];
  1012.  
  1013. static void
  1014. handle_checksum (args, len)
  1015.     char *args;
  1016.     int len;
  1017. {
  1018.     char *s;
  1019.     char buf[3];
  1020.     int i;
  1021.  
  1022.     if (stored_checksum_valid)
  1023.         error (1, 0, "Checksum received before last one was used");
  1024.  
  1025.     s = args;
  1026.     buf[2] = '\0';
  1027.     for (i = 0; i < 16; i++)
  1028.     {
  1029.         char *bufend;
  1030.  
  1031.     buf[0] = *s++;
  1032.     buf[1] = *s++;
  1033.     stored_checksum[i] = (char) strtol (buf, &bufend, 16);
  1034.     if (bufend != buf + 2)
  1035.         break;
  1036.     }
  1037.  
  1038.     if (i < 16 || *s != '\0')
  1039.         error (1, 0, "Invalid Checksum response: `%s'", args);
  1040.  
  1041.     stored_checksum_valid = 1;
  1042. }
  1043.  
  1044. static int stored_mode_valid;
  1045. static char *stored_mode;
  1046.  
  1047. static void handle_mode PROTO ((char *, int));
  1048.  
  1049. static void
  1050. handle_mode (args, len)
  1051.     char *args;
  1052.     int len;
  1053. {
  1054.     if (stored_mode_valid)
  1055.     error (1, 0, "protocol error: duplicate Mode");
  1056.     if (stored_mode != NULL)
  1057.     free (stored_mode);
  1058.     stored_mode = xstrdup (args);
  1059.     stored_mode_valid = 1;
  1060. }
  1061.  
  1062. /*
  1063.  * If we receive a patch, but the patch program fails to apply it, we
  1064.  * want to request the original file.  We keep a list of files whose
  1065.  * patches have failed.
  1066.  */
  1067.  
  1068. char **failed_patches;
  1069. int failed_patches_count;
  1070.  
  1071. struct update_entries_data
  1072. {
  1073.     enum {
  1074.       /*
  1075.        * We are just getting an Entries line; the local file is
  1076.        * correct.
  1077.        */
  1078.       UPDATE_ENTRIES_CHECKIN,
  1079.       /* We are getting the file contents as well.  */
  1080.       UPDATE_ENTRIES_UPDATE,
  1081.       /*
  1082.        * We are getting a patch against the existing local file, not
  1083.        * an entire new file.
  1084.        */
  1085.       UPDATE_ENTRIES_PATCH
  1086.     } contents;
  1087.  
  1088.     /*
  1089.      * String to put in the timestamp field or NULL to use the timestamp
  1090.      * of the file.
  1091.      */
  1092.     char *timestamp;
  1093. };
  1094.  
  1095. /* Update the Entries line for this file.  */
  1096. static void
  1097. update_entries (data_arg, ent_list, short_pathname, filename)
  1098.     char *data_arg;
  1099.     List *ent_list;
  1100.     char *short_pathname;
  1101.     char *filename;
  1102. {
  1103.     char *entries_line;
  1104.     struct update_entries_data *data = (struct update_entries_data *)data_arg;
  1105.  
  1106.     char *cp;
  1107.     char *user;
  1108.     char *vn;
  1109.     /* Timestamp field.  Always empty according to the protocol.  */
  1110.     char *ts;
  1111.     char *options;
  1112.     char *tag;
  1113.     char *date;
  1114.     char *tag_or_date;
  1115.     char *scratch_entries;
  1116.     int bin;
  1117.  
  1118.     read_line (&entries_line, 0);
  1119.  
  1120.     /*
  1121.      * Parse the entries line.
  1122.      */
  1123.     if (strcmp (command_name, "export") != 0)
  1124.     {
  1125.     scratch_entries = xstrdup (entries_line);
  1126.  
  1127.     if (scratch_entries[0] != '/')
  1128.         error (1, 0, "bad entries line `%s' from server", entries_line);
  1129.     user = scratch_entries + 1;
  1130.     if ((cp = strchr (user, '/')) == NULL)
  1131.         error (1, 0, "bad entries line `%s' from server", entries_line);
  1132.     *cp++ = '\0';
  1133.     vn = cp;
  1134.     if ((cp = strchr (vn, '/')) == NULL)
  1135.         error (1, 0, "bad entries line `%s' from server", entries_line);
  1136.     *cp++ = '\0';
  1137.     
  1138.     ts = cp;
  1139.     if ((cp = strchr (ts, '/')) == NULL)
  1140.         error (1, 0, "bad entries line `%s' from server", entries_line);
  1141.     *cp++ = '\0';
  1142.     options = cp;
  1143.     if ((cp = strchr (options, '/')) == NULL)
  1144.         error (1, 0, "bad entries line `%s' from server", entries_line);
  1145.     *cp++ = '\0';
  1146.     tag_or_date = cp;
  1147.  
  1148.     /* If a slash ends the tag_or_date, ignore everything after it.  */
  1149.     cp = strchr (tag_or_date, '/');
  1150.     if (cp != NULL)
  1151.         *cp = '\0';
  1152.     tag = (char *) NULL;
  1153.     date = (char *) NULL;
  1154.     if (*tag_or_date == 'T')
  1155.         tag = tag_or_date + 1;
  1156.     else if (*tag_or_date == 'D')
  1157.         date = tag_or_date + 1;
  1158.     }
  1159.     else
  1160.     /* For cvs export, assume it is a text file.  FIXME: This is
  1161.        broken behavior--we should be having the server tell us
  1162.        whether it is text or binary and dealing accordingly.  I
  1163.        think maybe we can parse the entries line, get the options,
  1164.        and then ignore the entries line otherwise, but I haven't
  1165.        checked to see whether the server sends the entries line
  1166.        correctly in this case.  */
  1167.     options = NULL;
  1168.  
  1169.     if (data->contents == UPDATE_ENTRIES_UPDATE
  1170.     || data->contents == UPDATE_ENTRIES_PATCH)
  1171.     {
  1172.     char *size_string;
  1173.     char *mode_string;
  1174.     int size;
  1175.     int fd;
  1176.     char *buf;
  1177.     char *temp_filename;
  1178.     int use_gzip, gzip_status;
  1179.     pid_t gzip_pid = 0;
  1180.  
  1181.     read_line (&mode_string, 0);
  1182.     
  1183.     read_line (&size_string, 0);
  1184.     if (size_string[0] == 'z')
  1185.     {
  1186.         use_gzip = 1;
  1187.         size = atoi (size_string+1);
  1188.     }
  1189.     else
  1190.     {
  1191.         use_gzip = 0;
  1192.         size = atoi (size_string);
  1193.     }
  1194.     free (size_string);
  1195.  
  1196.     temp_filename = xmalloc (strlen (filename) + 80);
  1197. #ifdef USE_VMS_FILENAMES
  1198.         /* A VMS rename of "blah.dat" to "foo" to implies a
  1199.            destination of "foo.dat" which is unfortinate for CVS */
  1200.        sprintf (temp_filename, "%s_new_", filename);
  1201. #else
  1202. #ifdef _POSIX_NO_TRUNC
  1203.     sprintf (temp_filename, ".new.%.9s", filename);
  1204. #else /* _POSIX_NO_TRUNC */
  1205.     sprintf (temp_filename, ".new.%s", filename);
  1206. #endif /* _POSIX_NO_TRUNC */
  1207. #endif /* USE_VMS_FILENAMES */
  1208.     buf = xmalloc (size);
  1209.  
  1210.         /* Some systems, like OS/2 and Windows NT, end lines with CRLF
  1211.            instead of just LF.  Format translation is done in the C
  1212.            library I/O funtions.  Here we tell them whether or not to
  1213.            convert -- if this file is marked "binary" with the RCS -kb
  1214.            flag, then we don't want to convert, else we do (because
  1215.            CVS assumes text files by default). */
  1216.  
  1217.     if (options)
  1218.         bin = !(strcmp (options, "-kb"));
  1219.     else
  1220.         bin = 0;
  1221.  
  1222.         fd = open (temp_filename,
  1223.                    O_WRONLY | O_CREAT | O_TRUNC | (bin ? OPEN_BINARY : 0),
  1224.                    0777);
  1225.  
  1226.     if (fd < 0)
  1227.         error (1, errno, "writing %s", short_pathname);
  1228.  
  1229.     if (use_gzip)
  1230.         fd = filter_through_gunzip (fd, 0, &gzip_pid);
  1231.  
  1232.     if (size > 0)
  1233.     {
  1234.           read_from_server (buf, size);
  1235.         
  1236.           if (write (fd, buf, size) != size)
  1237.             error (1, errno, "writing %s", short_pathname);
  1238.     }
  1239.  
  1240.     if (close (fd) < 0)
  1241.         error (1, errno, "writing %s", short_pathname);
  1242.     if (gzip_pid > 0)
  1243.     {
  1244.         if (waitpid (gzip_pid, &gzip_status, 0) == -1)
  1245.         error (1, errno, "waiting for gzip process %ld",
  1246.                (long) gzip_pid);
  1247.         else if (gzip_status != 0)
  1248.         error (1, 0, "gzip process exited %d", gzip_status);
  1249.     }
  1250.  
  1251.     gzip_pid = -1;
  1252.  
  1253.     /* Since gunzip writes files without converting LF to CRLF
  1254.        (a reasonable behavior), we now have a patch file in LF
  1255.        format.  Leave the file as is if we're just going to feed
  1256.        it to patch; patch can handle it.  However, if it's the
  1257.        final source file, convert it.  */
  1258.  
  1259.     if (data->contents == UPDATE_ENTRIES_UPDATE)
  1260.     {
  1261. #ifdef LINES_CRLF_TERMINATED
  1262.  
  1263.             /* `bin' is non-zero iff `options' contains "-kb", meaning
  1264.                 treat this file as binary. */
  1265.  
  1266.         if (use_gzip && (! bin))
  1267.         {
  1268.             convert_file (temp_filename, O_RDONLY | OPEN_BINARY,
  1269.                       filename, O_WRONLY | O_CREAT | O_TRUNC);
  1270.             if (unlink (temp_filename) < 0)
  1271.                 error (0, errno, "warning: couldn't delete %s",
  1272.                            temp_filename);
  1273.         }
  1274.         else
  1275.         rename_file (temp_filename, filename);
  1276.             
  1277. #else /* ! LINES_CRLF_TERMINATED */
  1278.         rename_file (temp_filename, filename);
  1279. #endif /* LINES_CRLF_TERMINATED */
  1280.     }
  1281.     else
  1282.     {
  1283.         int retcode;
  1284.         char backup[PATH_MAX];
  1285.         struct stat s;
  1286.  
  1287.         (void) sprintf (backup, "%s~", filename);
  1288.         (void) unlink_file (backup);
  1289.         if (!isfile (filename))
  1290.             error (1, 0, "patch original file %s does not exist",
  1291.                short_pathname);
  1292.         if (stat (temp_filename, &s) < 0)
  1293.             error (1, 1, "can't stat patch file %s", temp_filename);
  1294.         if (s.st_size == 0)
  1295.             retcode = 0;
  1296.         else
  1297.         {
  1298.             run_setup ("%s -f -s -b ~ %s %s", PATCH_PROGRAM,
  1299.                filename, temp_filename);
  1300.         retcode = run_exec (DEVNULL, RUN_TTY, RUN_TTY, RUN_NORMAL);
  1301.         }
  1302.         /* FIXME: should we really be silently ignoring errors?  */
  1303.         (void) unlink_file (temp_filename);
  1304.         if (retcode == 0)
  1305.         {
  1306.         /* FIXME: should we really be silently ignoring errors?  */
  1307.         (void) unlink_file (backup);
  1308.         }
  1309.         else
  1310.         {
  1311.             int old_errno = errno;
  1312.         char *path_tmp;
  1313.  
  1314.             if (isfile (backup))
  1315.             rename_file (backup, filename);
  1316.        
  1317.         /* Get rid of the patch reject file.  */
  1318.         path_tmp = xmalloc (strlen (filename) + 10);
  1319.         strcpy (path_tmp, filename);
  1320.         strcat (path_tmp, ".rej");
  1321.         /* FIXME: should we really be silently ignoring errors?  */
  1322.         (void) unlink_file (path_tmp);
  1323.         free (path_tmp);
  1324.  
  1325.         /* Save this file to retrieve later.  */
  1326.         failed_patches =
  1327.             (char **) xrealloc ((char *) failed_patches,
  1328.                     ((failed_patches_count + 1)
  1329.                      * sizeof (char *)));
  1330.         failed_patches[failed_patches_count] =
  1331.             xstrdup (short_pathname);
  1332.         ++failed_patches_count;
  1333.  
  1334.         error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
  1335.                "could not patch %s%s", filename,
  1336.                retcode == -1 ? "" : "; will refetch");
  1337.  
  1338.         stored_checksum_valid = 0;
  1339.  
  1340.         return;
  1341.         }
  1342.     }
  1343.     free (temp_filename);
  1344.  
  1345.     if (stored_checksum_valid)
  1346.     {
  1347.         FILE *e;
  1348.         struct MD5Context context;
  1349.         unsigned char buf[8192];
  1350.         unsigned len;
  1351.         unsigned char checksum[16];
  1352.  
  1353.         /*
  1354.          * Compute the MD5 checksum.  This will normally only be
  1355.          * used when receiving a patch, so we always compute it
  1356.          * here on the final file, rather than on the received
  1357.          * data.
  1358.          *
  1359.          * Note that if the file is a text file, we should read it
  1360.          * here using text mode, so its lines will be terminated the same
  1361.          * way they were transmitted.
  1362.          */
  1363.         e = fopen (filename, "r");
  1364.         if (e == NULL)
  1365.             error (1, errno, "could not open %s", short_pathname);
  1366.  
  1367.         MD5Init (&context);
  1368.         while ((len = fread (buf, 1, sizeof buf, e)) != 0)
  1369.         MD5Update (&context, buf, len);
  1370.         if (ferror (e))
  1371.         error (1, errno, "could not read %s", short_pathname);
  1372.         MD5Final (checksum, &context);
  1373.  
  1374.         fclose (e);
  1375.  
  1376.         stored_checksum_valid = 0;
  1377.  
  1378.         if (memcmp (checksum, stored_checksum, 16) != 0)
  1379.         {
  1380.             if (data->contents != UPDATE_ENTRIES_PATCH)
  1381.             error (1, 0, "checksum failure on %s",
  1382.                short_pathname);
  1383.  
  1384.         error (0, 0,
  1385.                "checksum failure after patch to %s; will refetch",
  1386.                short_pathname);
  1387.  
  1388.         /* Save this file to retrieve later.  */
  1389.         failed_patches =
  1390.             (char **) xrealloc ((char *) failed_patches,
  1391.                     ((failed_patches_count + 1)
  1392.                      * sizeof (char *)));
  1393.         failed_patches[failed_patches_count] =
  1394.             xstrdup (short_pathname);
  1395.         ++failed_patches_count;
  1396.  
  1397.         return;
  1398.         }
  1399.     }
  1400.  
  1401.         {
  1402.         /* FIXME: we should be respecting the umask.  */
  1403.         int status = change_mode (filename, mode_string);
  1404.         if (status != 0)
  1405.         error (0, status, "cannot change mode of %s", short_pathname);
  1406.     }
  1407.  
  1408.     free (mode_string);
  1409.     free (buf);
  1410.     }
  1411.  
  1412.     if (stored_mode_valid)
  1413.     change_mode (filename, stored_mode);
  1414.     stored_mode_valid = 0;
  1415.  
  1416.     /*
  1417.      * Process the entries line.  Do this after we've written the file,
  1418.      * since we need the timestamp.
  1419.      */
  1420.     if (strcmp (command_name, "export") != 0)
  1421.     {
  1422.     char *local_timestamp;
  1423.     char *file_timestamp;
  1424.  
  1425.     local_timestamp = data->timestamp;
  1426.     if (local_timestamp == NULL || ts[0] == '+')
  1427.         file_timestamp = time_stamp (filename);
  1428.     else
  1429.         file_timestamp = NULL;
  1430.  
  1431.     /*
  1432.      * These special version numbers signify that it is not up to
  1433.      * date.  Create a dummy timestamp which will never compare
  1434.      * equal to the timestamp of the file.
  1435.      */
  1436.     if (vn[0] == '\0' || vn[0] == '0' || vn[0] == '-')
  1437.         local_timestamp = "dummy timestamp";
  1438.     else if (local_timestamp == NULL)
  1439.     {
  1440.         local_timestamp = file_timestamp;
  1441.         mark_up_to_date (filename);
  1442.     }
  1443.  
  1444.     Register (ent_list, filename, vn, local_timestamp,
  1445.           options, tag, date, ts[0] == '+' ? file_timestamp : NULL);
  1446.  
  1447.     if (file_timestamp)
  1448.         free (file_timestamp);
  1449.  
  1450.     free (scratch_entries);
  1451.     }
  1452.     free (entries_line);
  1453. }
  1454.  
  1455. static void
  1456. handle_checked_in (args, len)
  1457.     char *args;
  1458.     int len;
  1459. {
  1460.     struct update_entries_data dat;
  1461.     dat.contents = UPDATE_ENTRIES_CHECKIN;
  1462.     dat.timestamp = NULL;
  1463.     call_in_directory (args, update_entries, (char *)&dat);
  1464. }
  1465.  
  1466. static void
  1467. handle_new_entry (args, len)
  1468.     char *args;
  1469.     int len;
  1470. {
  1471.     struct update_entries_data dat;
  1472.     dat.contents = UPDATE_ENTRIES_CHECKIN;
  1473.     dat.timestamp = "dummy timestamp from new-entry";
  1474.     call_in_directory (args, update_entries, (char *)&dat);
  1475. }
  1476.  
  1477. static void
  1478. handle_updated (args, len)
  1479.     char *args;
  1480.     int len;
  1481. {
  1482.     struct update_entries_data dat;
  1483.     dat.contents = UPDATE_ENTRIES_UPDATE;
  1484.     dat.timestamp = NULL;
  1485.     call_in_directory (args, update_entries, (char *)&dat);
  1486. }
  1487.  
  1488. static void
  1489. handle_merged (args, len)
  1490.     char *args;
  1491.     int len;
  1492. {
  1493.     struct update_entries_data dat;
  1494.     dat.contents = UPDATE_ENTRIES_UPDATE;
  1495.     dat.timestamp = "Result of merge";
  1496.     call_in_directory (args, update_entries, (char *)&dat);
  1497. }
  1498.  
  1499. static void
  1500. handle_patched (args, len)
  1501.      char *args;
  1502.      int len;
  1503. {
  1504.     struct update_entries_data dat;
  1505.     dat.contents = UPDATE_ENTRIES_PATCH;
  1506.     dat.timestamp = NULL;
  1507.     call_in_directory (args, update_entries, (char *)&dat);
  1508. }
  1509.  
  1510. static void
  1511. remove_entry (data, ent_list, short_pathname, filename)
  1512.     char *data;
  1513.     List *ent_list;
  1514.     char *short_pathname;
  1515.     char *filename;
  1516. {
  1517.     Scratch_Entry (ent_list, filename);
  1518. }
  1519.  
  1520. static void
  1521. handle_remove_entry (args, len)
  1522.     char *args;
  1523.     int len;
  1524. {
  1525.     call_in_directory (args, remove_entry, (char *)NULL);
  1526. }
  1527.  
  1528. static void
  1529. remove_entry_and_file (data, ent_list, short_pathname, filename)
  1530.     char *data;
  1531.     List *ent_list;
  1532.     char *short_pathname;
  1533.     char *filename;
  1534. {
  1535.     Scratch_Entry (ent_list, filename);
  1536.     if (unlink_file (filename) < 0)
  1537.     error (0, errno, "unable to remove %s", short_pathname);
  1538. }
  1539.  
  1540. static void
  1541. handle_removed (args, len)
  1542.     char *args;
  1543.     int len;
  1544. {
  1545.     call_in_directory (args, remove_entry_and_file, (char *)NULL);
  1546. }
  1547.  
  1548. /* Is this the top level (directory containing CVSROOT)?  */
  1549. static int
  1550. is_cvsroot_level (pathname)
  1551.     char *pathname;
  1552. {
  1553.     char *short_pathname;
  1554.  
  1555.     if (strcmp (toplevel_repos, server_cvsroot) != 0)
  1556.     return 0;
  1557.  
  1558.     if (!use_directory)
  1559.     {
  1560.     if (strncmp (pathname, server_cvsroot, strlen (server_cvsroot)) != 0)
  1561.         error (1, 0,
  1562.            "server bug: pathname `%s' doesn't specify file in `%s'",
  1563.            pathname, server_cvsroot);
  1564.     short_pathname = pathname + strlen (server_cvsroot) + 1;
  1565.     if (short_pathname[-1] != '/')
  1566.         error (1, 0,
  1567.            "server bug: pathname `%s' doesn't specify file in `%s'",
  1568.            pathname, server_cvsroot);
  1569.     return strchr (short_pathname, '/') == NULL;
  1570.     }
  1571.     else
  1572.     {
  1573.     return strchr (pathname, '/') == NULL;
  1574.     }
  1575. }
  1576.  
  1577. static void
  1578. set_static (data, ent_list, short_pathname, filename)
  1579.     char *data;
  1580.     List *ent_list;
  1581.     char *short_pathname;
  1582.     char *filename;
  1583. {
  1584.     FILE *fp;
  1585.     fp = open_file (CVSADM_ENTSTAT, "w+");
  1586.     if (fclose (fp) == EOF)
  1587.         error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
  1588. }
  1589.  
  1590. static void
  1591. handle_set_static_directory (args, len)
  1592.     char *args;
  1593.     int len;
  1594. {
  1595.     if (strcmp (command_name, "export") == 0)
  1596.     {
  1597.     /* Swallow the repository.  */
  1598.     read_line (NULL, 0);
  1599.     return;
  1600.     }
  1601.     call_in_directory (args, set_static, (char *)NULL);
  1602. }
  1603.  
  1604. static void
  1605. clear_static (data, ent_list, short_pathname, filename)
  1606.     char *data;
  1607.     List *ent_list;
  1608.     char *short_pathname;
  1609.     char *filename;
  1610. {
  1611.     if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
  1612.         error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
  1613. }
  1614.  
  1615. static void
  1616. handle_clear_static_directory (pathname, len)
  1617.     char *pathname;
  1618.     int len;
  1619. {
  1620.     if (strcmp (command_name, "export") == 0)
  1621.     {
  1622.     /* Swallow the repository.  */
  1623.     read_line (NULL, 0);
  1624.     return;
  1625.     }
  1626.  
  1627.     if (is_cvsroot_level (pathname))
  1628.     {
  1629.         /*
  1630.      * Top level (directory containing CVSROOT).  This seems to normally
  1631.      * lack a CVS directory, so don't try to create files in it.
  1632.      */
  1633.     return;
  1634.     }
  1635.     call_in_directory (pathname, clear_static, (char *)NULL);
  1636. }
  1637.  
  1638. static void
  1639. set_sticky (data, ent_list, short_pathname, filename)
  1640.     char *data;
  1641.     List *ent_list;
  1642.     char *short_pathname;
  1643.     char *filename;
  1644. {
  1645.     char *tagspec;
  1646.     FILE *f;
  1647.  
  1648.     read_line (&tagspec, 0);
  1649.     f = open_file (CVSADM_TAG, "w+");
  1650.     if (fprintf (f, "%s\n", tagspec) < 0)
  1651.     error (1, errno, "writing %s", CVSADM_TAG);
  1652.     if (fclose (f) == EOF)
  1653.     error (1, errno, "closing %s", CVSADM_TAG);
  1654.     free (tagspec);
  1655. }
  1656.  
  1657. static void
  1658. handle_set_sticky (pathname, len)
  1659.     char *pathname;
  1660.     int len;
  1661. {
  1662.     if (strcmp (command_name, "export") == 0)
  1663.     {
  1664.     /* Swallow the repository.  */
  1665.     read_line (NULL, 0);
  1666.         /* Swallow the tag line.  */
  1667.     (void) read_line (NULL, 0);
  1668.     return;
  1669.     }
  1670.     if (is_cvsroot_level (pathname))
  1671.     {
  1672.         /*
  1673.      * Top level (directory containing CVSROOT).  This seems to normally
  1674.      * lack a CVS directory, so don't try to create files in it.
  1675.      */
  1676.  
  1677.     /* Swallow the repository.  */
  1678.     read_line (NULL, 0);
  1679.         /* Swallow the tag line.  */
  1680.     (void) read_line (NULL, 0);
  1681.     return;
  1682.     }
  1683.  
  1684.     call_in_directory (pathname, set_sticky, (char *)NULL);
  1685. }
  1686.  
  1687. static void
  1688. clear_sticky (data, ent_list, short_pathname, filename)
  1689.     char *data;
  1690.     List *ent_list;
  1691.     char *short_pathname;
  1692.     char *filename;
  1693. {
  1694.     if (unlink_file (CVSADM_TAG) < 0 && ! existence_error (errno))
  1695.     error (1, errno, "cannot remove %s", CVSADM_TAG);
  1696. }
  1697.  
  1698. static void
  1699. handle_clear_sticky (pathname, len)
  1700.     char *pathname;
  1701.     int len;
  1702. {
  1703.     if (strcmp (command_name, "export") == 0)
  1704.     {
  1705.     /* Swallow the repository.  */
  1706.     read_line (NULL, 0);
  1707.     return;
  1708.     }
  1709.  
  1710.     if (is_cvsroot_level (pathname))
  1711.     {
  1712.         /*
  1713.      * Top level (directory containing CVSROOT).  This seems to normally
  1714.      * lack a CVS directory, so don't try to create files in it.
  1715.      */
  1716.     return;
  1717.     }
  1718.  
  1719.     call_in_directory (pathname, clear_sticky, (char *)NULL);
  1720. }
  1721.  
  1722.  
  1723. static void template PROTO ((char *, List *, char *, char *));
  1724.  
  1725. static void
  1726. template (data, ent_list, short_pathname, filename)
  1727.     char *data;
  1728.     List *ent_list;
  1729.     char *short_pathname;
  1730.     char *filename;
  1731. {
  1732.     /* FIXME: should be computing second argument from CVSADM_TEMPLATE
  1733.        and short_pathname.  */
  1734.     read_counted_file (CVSADM_TEMPLATE, "<CVS/Template file>");
  1735. }
  1736.  
  1737. static void handle_template PROTO ((char *, int));
  1738.  
  1739. static void
  1740. handle_template (pathname, len)
  1741.     char *pathname;
  1742.     int len;
  1743. {
  1744.     call_in_directory (pathname, template, NULL);
  1745. }
  1746.  
  1747.  
  1748. struct save_prog {
  1749.     char *name;
  1750.     char *dir;
  1751.     struct save_prog *next;
  1752. };
  1753.  
  1754. static struct save_prog *checkin_progs;
  1755. static struct save_prog *update_progs;
  1756.  
  1757. /*
  1758.  * Unlike some responses this doesn't include the repository.  So we can't
  1759.  * just call call_in_directory and have the right thing happen; we save up
  1760.  * the requests and do them at the end.
  1761.  */
  1762. static void
  1763. handle_set_checkin_prog (args, len)
  1764.     char *args;
  1765.     int len;
  1766. {
  1767.     char *prog;
  1768.     struct save_prog *p;
  1769.     read_line (&prog, 0);
  1770.     p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
  1771.     p->next = checkin_progs;
  1772.     p->dir = xstrdup (args);
  1773.     p->name = prog;
  1774.     checkin_progs = p;
  1775. }
  1776.     
  1777. static void
  1778. handle_set_update_prog (args, len)
  1779.     char *args;
  1780.     int len;
  1781. {
  1782.     char *prog;
  1783.     struct save_prog *p;
  1784.     read_line (&prog, 0);
  1785.     p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
  1786.     p->next = update_progs;
  1787.     p->dir = xstrdup (args);
  1788.     p->name = prog;
  1789.     update_progs = p;
  1790. }
  1791.  
  1792. static void do_deferred_progs PROTO((void));
  1793.  
  1794. static void
  1795. do_deferred_progs ()
  1796. {
  1797.     struct save_prog *p;
  1798.     struct save_prog *q;
  1799.  
  1800.     char fname[PATH_MAX];
  1801.     FILE *f;
  1802.     if (toplevel_wd[0] != '\0')
  1803.       {
  1804.     if (chdir (toplevel_wd) < 0)
  1805.       error (1, errno, "could not chdir to %s", toplevel_wd);
  1806.       }
  1807.     for (p = checkin_progs; p != NULL; )
  1808.     {
  1809.     sprintf (fname, "%s/%s", p->dir, CVSADM_CIPROG);
  1810.     f = open_file (fname, "w");
  1811.     if (fprintf (f, "%s\n", p->name) < 0)
  1812.         error (1, errno, "writing %s", fname);
  1813.     if (fclose (f) == EOF)
  1814.         error (1, errno, "closing %s", fname);
  1815.     free (p->name);
  1816.     free (p->dir);
  1817.     q = p->next;
  1818.     free (p);
  1819.     p = q;
  1820.     }
  1821.     checkin_progs = NULL;
  1822.     for (p = update_progs; p != NULL; p = p->next)
  1823.     {
  1824.     sprintf (fname, "%s/%s", p->dir, CVSADM_UPROG);
  1825.     f = open_file (fname, "w");
  1826.     if (fprintf (f, "%s\n", p->name) < 0)
  1827.         error (1, errno, "writing %s", fname);
  1828.     if (fclose (f) == EOF)
  1829.         error (1, errno, "closing %s", fname);
  1830.     free (p->name);
  1831.     free (p->dir);
  1832.     free (p);
  1833.     }
  1834.     update_progs = NULL;
  1835. }
  1836.  
  1837. static int client_isemptydir PROTO((char *));
  1838.  
  1839. /*
  1840.  * Returns 1 if the argument directory exists and is completely empty,
  1841.  * other than the existence of the CVS directory entry.  Zero otherwise.
  1842.  */
  1843. static int
  1844. client_isemptydir (dir)
  1845.     char *dir;
  1846. {
  1847.     DIR *dirp;
  1848.     struct dirent *dp;
  1849.  
  1850.     if ((dirp = opendir (dir)) == NULL)
  1851.     {
  1852.     if (! existence_error (errno))
  1853.         error (0, errno, "cannot open directory %s for empty check", dir);
  1854.     return (0);
  1855.     }
  1856.     errno = 0;
  1857.     while ((dp = readdir (dirp)) != NULL)
  1858.     {
  1859.     if (strcmp (dp->d_name, ".") != 0 && strcmp (dp->d_name, "..") != 0 &&
  1860.         strcmp (dp->d_name, CVSADM) != 0)
  1861.     {
  1862.         (void) closedir (dirp);
  1863.         return (0);
  1864.     }
  1865.     }
  1866.     if (errno != 0)
  1867.     {
  1868.     error (0, errno, "cannot read directory %s", dir);
  1869.     (void) closedir (dirp);
  1870.     return (0);
  1871.     }
  1872.     (void) closedir (dirp);
  1873.     return (1);
  1874. }
  1875.  
  1876. struct save_dir {
  1877.     char *dir;
  1878.     struct save_dir *next;
  1879. };
  1880.  
  1881. struct save_dir *prune_candidates;
  1882.  
  1883. static void
  1884. add_prune_candidate (dir)
  1885.     char *dir;
  1886. {
  1887.     struct save_dir *p;
  1888.  
  1889.     if (dir[0] == '.' && dir[1] == '\0')
  1890.     return;
  1891.     p = (struct save_dir *) xmalloc (sizeof (struct save_dir));
  1892.     p->dir = xstrdup (dir);
  1893.     p->next = prune_candidates;
  1894.     prune_candidates = p;
  1895. }
  1896.  
  1897. static void process_prune_candidates PROTO((void));
  1898.  
  1899. static void
  1900. process_prune_candidates ()
  1901. {
  1902.     struct save_dir *p;
  1903.     struct save_dir *q;
  1904.  
  1905.     if (toplevel_wd[0] != '\0')
  1906.       {
  1907.     if (chdir (toplevel_wd) < 0)
  1908.       error (1, errno, "could not chdir to %s", toplevel_wd);
  1909.       }
  1910.     for (p = prune_candidates; p != NULL; )
  1911.     {
  1912.     if (client_isemptydir (p->dir))
  1913.     {
  1914.           unlink_file_dir (p->dir);
  1915.     }
  1916.     free (p->dir);
  1917.     q = p->next;
  1918.     free (p);
  1919.     p = q;
  1920.     }
  1921. }
  1922.  
  1923. /* Send a Repository line.  */
  1924.  
  1925. static char *last_repos;
  1926. static char *last_update_dir;
  1927.  
  1928. static void send_repository PROTO((char *, char *, char *));
  1929.  
  1930. static void
  1931. send_repository (dir, repos, update_dir)
  1932.     char *dir;
  1933.     char *repos;
  1934.     char *update_dir;
  1935. {
  1936.     char *adm_name;
  1937.  
  1938.     /* FIXME: this is probably not the best place to check; I wish I
  1939.      * knew where in here's callers to really trap this bug.  To
  1940.      * reproduce the bug, just do this:
  1941.      * 
  1942.      *       mkdir junk
  1943.      *       cd junk
  1944.      *       cvs -d some_repos update foo
  1945.      *
  1946.      * Poof, CVS seg faults and dies!  It's because it's trying to
  1947.      * send a NULL string to the server but dies in send_to_server.
  1948.      * That string was supposed to be the repository, but it doesn't
  1949.      * get set because there's no CVSADM dir, and somehow it's not
  1950.      * getting set from the -d argument either... ?
  1951.      */
  1952.     if (repos == NULL)
  1953.     {
  1954.         /* Lame error.  I want a real fix but can't stay up to track
  1955.            this down right now. */
  1956.         error (1, 0, "no repository");
  1957.     }
  1958.  
  1959.     if (update_dir == NULL || update_dir[0] == '\0')
  1960.     update_dir = ".";
  1961.  
  1962.     if (last_repos != NULL
  1963.     && strcmp (repos, last_repos) == 0
  1964.     && last_update_dir != NULL
  1965.     && strcmp (update_dir, last_update_dir) == 0)
  1966.     /* We've already sent it.  */
  1967.     return;
  1968.  
  1969.     if (client_prune_dirs)
  1970.     add_prune_candidate (update_dir);
  1971.  
  1972.     /* 80 is large enough for any of CVSADM_*.  */
  1973.     adm_name = xmalloc (strlen (dir) + 80);
  1974.  
  1975.     if (use_directory == -1)
  1976.     use_directory = supported_request ("Directory");
  1977.  
  1978.     if (use_directory)
  1979.     {
  1980.     send_to_server ("Directory ", 0);
  1981.     send_to_server (update_dir, 0);
  1982.     send_to_server ("\012", 1);
  1983.     send_to_server (repos, 0);
  1984.     send_to_server ("\012", 1);
  1985.     }
  1986.     else
  1987.     {
  1988.     send_to_server ("Repository ", 0);
  1989.     send_to_server (repos, 0);
  1990.     send_to_server ("\012", 1);
  1991.     }
  1992.     if (supported_request ("Static-directory"))
  1993.     {
  1994.     adm_name[0] = '\0';
  1995.     if (dir[0] != '\0')
  1996.     {
  1997.         strcat (adm_name, dir);
  1998.         strcat (adm_name, "/");
  1999.     }
  2000.     strcat (adm_name, CVSADM_ENTSTAT);
  2001.     if (isreadable (adm_name))
  2002.     {
  2003.         send_to_server ("Static-directory\012", 0);
  2004.     }
  2005.     }
  2006.     if (supported_request ("Sticky"))
  2007.     {
  2008.     FILE *f;
  2009.     if (dir[0] == '\0')
  2010.         strcpy (adm_name, CVSADM_TAG);
  2011.     else
  2012.         sprintf (adm_name, "%s/%s", dir, CVSADM_TAG);
  2013.  
  2014.     f = fopen (adm_name, "r");
  2015.     if (f == NULL)
  2016.     {
  2017.         if (! existence_error (errno))
  2018.         error (1, errno, "reading %s", adm_name);
  2019.     }
  2020.     else
  2021.     {
  2022.         char line[80];
  2023.         char *nl;
  2024.         send_to_server ("Sticky ", 0);
  2025.         while (fgets (line, sizeof (line), f) != NULL)
  2026.         {
  2027.         send_to_server (line, 0);
  2028.         nl = strchr (line, '\n');
  2029.         if (nl != NULL)
  2030.             break;
  2031.         }
  2032.         if (nl == NULL)
  2033.                 send_to_server ("\012", 1);
  2034.         if (fclose (f) == EOF)
  2035.         error (0, errno, "closing %s", adm_name);
  2036.     }
  2037.     }
  2038.     if (supported_request ("Checkin-prog"))
  2039.     {
  2040.     FILE *f;
  2041.     if (dir[0] == '\0')
  2042.         strcpy (adm_name, CVSADM_CIPROG);
  2043.     else
  2044.         sprintf (adm_name, "%s/%s", dir, CVSADM_CIPROG);
  2045.  
  2046.     f = fopen (adm_name, "r");
  2047.     if (f == NULL)
  2048.     {
  2049.         if (! existence_error (errno))
  2050.         error (1, errno, "reading %s", adm_name);
  2051.     }
  2052.     else
  2053.     {
  2054.         char line[80];
  2055.         char *nl;
  2056.  
  2057.         send_to_server ("Checkin-prog ", 0);
  2058.  
  2059.         while (fgets (line, sizeof (line), f) != NULL)
  2060.         {
  2061.         send_to_server (line, 0);
  2062.  
  2063.         nl = strchr (line, '\n');
  2064.         if (nl != NULL)
  2065.             break;
  2066.         }
  2067.         if (nl == NULL)
  2068.         send_to_server ("\012", 1);
  2069.         if (fclose (f) == EOF)
  2070.         error (0, errno, "closing %s", adm_name);
  2071.     }
  2072.     }
  2073.     if (supported_request ("Update-prog"))
  2074.     {
  2075.     FILE *f;
  2076.     if (dir[0] == '\0')
  2077.         strcpy (adm_name, CVSADM_UPROG);
  2078.     else
  2079.         sprintf (adm_name, "%s/%s", dir, CVSADM_UPROG);
  2080.  
  2081.     f = fopen (adm_name, "r");
  2082.     if (f == NULL)
  2083.     {
  2084.         if (! existence_error (errno))
  2085.         error (1, errno, "reading %s", adm_name);
  2086.     }
  2087.     else
  2088.     {
  2089.         char line[80];
  2090.         char *nl;
  2091.  
  2092.         send_to_server ("Update-prog ", 0);
  2093.  
  2094.         while (fgets (line, sizeof (line), f) != NULL)
  2095.         {
  2096.         send_to_server (line, 0);
  2097.  
  2098.         nl = strchr (line, '\n');
  2099.         if (nl != NULL)
  2100.             break;
  2101.         }
  2102.         if (nl == NULL)
  2103.         send_to_server ("\012", 1);
  2104.         if (fclose (f) == EOF)
  2105.         error (0, errno, "closing %s", adm_name);
  2106.     }
  2107.     }
  2108.     free (adm_name);
  2109.     if (last_repos != NULL)
  2110.     free (last_repos);
  2111.     if (last_update_dir != NULL)
  2112.     free (last_update_dir);
  2113.     last_repos = xstrdup (repos);
  2114.     last_update_dir = xstrdup (update_dir);
  2115. }
  2116.  
  2117. /* Send a Repository line and set toplevel_repos.  */
  2118. static void send_a_repository PROTO((char *, char *, char *));
  2119.  
  2120. static void
  2121. send_a_repository (dir, repository, update_dir)
  2122.     char *dir;
  2123.     char *repository;
  2124.     char *update_dir;
  2125. {
  2126.     if (toplevel_repos == NULL && repository != NULL)
  2127.     {
  2128.     if (update_dir[0] == '\0'
  2129.         || (update_dir[0] == '.' && update_dir[1] == '\0'))
  2130.         toplevel_repos = xstrdup (repository);
  2131.     else
  2132.     {
  2133.         /*
  2134.          * Get the repository from a CVS/Repository file if update_dir
  2135.          * is absolute.  This is not correct in general, because
  2136.          * the CVS/Repository file might not be the top-level one.
  2137.          * This is for cases like "cvs update /foo/bar" (I'm not
  2138.          * sure it matters what toplevel_repos we get, but it does
  2139.          * matter that we don't hit the "internal error" code below).
  2140.          */
  2141.         if (update_dir[0] == '/')
  2142.         toplevel_repos = Name_Repository (update_dir, update_dir);
  2143.         else
  2144.         {
  2145.         /*
  2146.          * Guess the repository of that directory by looking at a
  2147.          * subdirectory and removing as many pathname components
  2148.          * as are in update_dir.  I think that will always (or at
  2149.          * least almost always) be 1.
  2150.          *
  2151.          * So this deals with directories which have been
  2152.          * renamed, though it doesn't necessarily deal with
  2153.          * directories which have been put inside other
  2154.          * directories (and cvs invoked on the containing
  2155.          * directory).  I'm not sure the latter case needs to
  2156.          * work.
  2157.          */
  2158.         /*
  2159.          * This gets toplevel_repos wrong for "cvs update ../foo"
  2160.          * but I'm not sure toplevel_repos matters in that case.
  2161.          */
  2162.         int slashes_in_update_dir;
  2163.         int slashes_skipped;
  2164.         char *p;
  2165.  
  2166.         slashes_in_update_dir = 0;
  2167.         for (p = update_dir; *p != '\0'; ++p)
  2168.             if (*p == '/')
  2169.             ++slashes_in_update_dir;
  2170.  
  2171.         slashes_skipped = 0;
  2172.         p = repository + strlen (repository);
  2173.         while (1)
  2174.         {
  2175.             if (p == repository)
  2176.             error (1, 0,
  2177.                    "internal error: not enough slashes in %s",
  2178.                    repository);
  2179.             if (*p == '/')
  2180.             ++slashes_skipped;
  2181.             if (slashes_skipped < slashes_in_update_dir + 1)
  2182.             --p;
  2183.             else
  2184.             break;
  2185.         }
  2186.         toplevel_repos = xmalloc (p - repository + 1);
  2187.         /* Note that we don't copy the trailing '/'.  */
  2188.         strncpy (toplevel_repos, repository, p - repository);
  2189.         toplevel_repos[p - repository] = '\0';
  2190.         }
  2191.     }
  2192.     }
  2193.  
  2194.     send_repository (dir, repository, update_dir);
  2195. }
  2196.  
  2197. /* The "expanded" modules.  */
  2198. static int modules_count;
  2199. static int modules_allocated;
  2200. static char **modules_vector;
  2201.  
  2202. static void
  2203. handle_module_expansion (args, len)
  2204.     char *args;
  2205.     int len;
  2206. {
  2207.     if (modules_vector == NULL)
  2208.     {
  2209.     modules_allocated = 1; /* Small for testing */
  2210.     modules_vector = (char **) xmalloc
  2211.       (modules_allocated * sizeof (modules_vector[0]));
  2212.     }
  2213.     else if (modules_count >= modules_allocated)
  2214.     {
  2215.     modules_allocated *= 2;
  2216.     modules_vector = (char **) xrealloc
  2217.       ((char *) modules_vector,
  2218.        modules_allocated * sizeof (modules_vector[0]));
  2219.     }
  2220.     modules_vector[modules_count] = xmalloc (strlen (args) + 1);
  2221.     strcpy (modules_vector[modules_count], args);
  2222.     ++modules_count;
  2223. }
  2224.  
  2225. /* Original, not "expanded" modules.  */
  2226. static int module_argc;
  2227. static char **module_argv;
  2228.  
  2229. void
  2230. client_expand_modules (argc, argv, local)
  2231.     int argc;
  2232.     char **argv;
  2233.     int local;
  2234. {
  2235.     int errs;
  2236.     int i;
  2237.  
  2238.     module_argc = argc;
  2239.     module_argv = (char **) xmalloc ((argc + 1) * sizeof (module_argv[0]));
  2240.     for (i = 0; i < argc; ++i)
  2241.     module_argv[i] = xstrdup (argv[i]);
  2242.     module_argv[argc] = NULL;
  2243.  
  2244.     for (i = 0; i < argc; ++i)
  2245.     send_arg (argv[i]);
  2246.     send_a_repository ("", server_cvsroot, "");
  2247.  
  2248.     send_to_server ("expand-modules\012", 0);
  2249.  
  2250.     errs = get_server_responses ();
  2251.     if (last_repos != NULL)
  2252.         free (last_repos);
  2253.     last_repos = NULL;
  2254.     if (last_update_dir != NULL)
  2255.         free (last_update_dir);
  2256.     last_update_dir = NULL;
  2257.     if (errs)
  2258.     error (errs, 0, "cannot expand modules");
  2259. }
  2260.  
  2261. void
  2262. client_send_expansions (local)
  2263.      int local;
  2264. {
  2265.     int i;
  2266.     char *argv[1];
  2267.  
  2268.     /* Send the original module names.  The "expanded" module name might
  2269.        not be suitable as an argument to a co request (e.g. it might be
  2270.        the result of a -d argument in the modules file).  It might be
  2271.        cleaner if we genuinely expanded module names, all the way to a
  2272.        local directory and repository, but that isn't the way it works
  2273.        now.  */
  2274.     send_file_names (module_argc, module_argv, 0);
  2275.  
  2276.     for (i = 0; i < modules_count; ++i)
  2277.     {
  2278.     argv[0] = modules_vector[i];
  2279.     if (isfile (argv[0]))
  2280.         send_files (1, argv, local, 0);
  2281.     }
  2282.     send_a_repository ("", server_cvsroot, "");
  2283. }
  2284.  
  2285. void
  2286. client_nonexpanded_setup ()
  2287. {
  2288.     send_a_repository ("", server_cvsroot, "");
  2289. }
  2290.  
  2291. static void
  2292. handle_m (args, len)
  2293.     char *args;
  2294.     int len;
  2295. {
  2296.   fwrite (args, len, sizeof (*args), stdout);
  2297.   putc ('\n', stdout);
  2298. }
  2299.  
  2300. static void
  2301. handle_e (args, len)
  2302.     char *args;
  2303.     int len;
  2304. {
  2305.   fwrite (args, len, sizeof (*args), stderr);
  2306.   putc ('\n', stderr);
  2307. }
  2308.  
  2309. #endif /* CLIENT_SUPPORT */
  2310. #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
  2311.  
  2312. /* This table must be writeable if the server code is included.  */
  2313. struct response responses[] =
  2314. {
  2315. #ifdef CLIENT_SUPPORT
  2316. #define RSP_LINE(n, f, t, s) {n, f, t, s}
  2317. #else /* ! CLIENT_SUPPORT */
  2318. #define RSP_LINE(n, f, t, s) {n, s}
  2319. #endif /* CLIENT_SUPPORT */
  2320.  
  2321.     RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
  2322.     RSP_LINE("error", handle_error, response_type_error, rs_essential),
  2323.     RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
  2324.        rs_essential),
  2325.     RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
  2326.        rs_essential),
  2327.     RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
  2328.     RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
  2329.     RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
  2330.     RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
  2331.     RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
  2332.     RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
  2333.     RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
  2334.     RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
  2335.     RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
  2336.        rs_optional),
  2337.     RSP_LINE("Set-static-directory", handle_set_static_directory,
  2338.        response_type_normal,
  2339.        rs_optional),
  2340.     RSP_LINE("Clear-static-directory", handle_clear_static_directory,
  2341.        response_type_normal,
  2342.        rs_optional),
  2343.     RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
  2344.        rs_optional),
  2345.     RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
  2346.        rs_optional),
  2347.     RSP_LINE("Template", handle_template, response_type_normal,
  2348.        rs_optional),
  2349.     RSP_LINE("Set-checkin-prog", handle_set_checkin_prog, response_type_normal,
  2350.        rs_optional),
  2351.     RSP_LINE("Set-update-prog", handle_set_update_prog, response_type_normal,
  2352.        rs_optional),
  2353.     RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
  2354.     RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
  2355.        rs_optional),
  2356.     RSP_LINE("M", handle_m, response_type_normal, rs_essential),
  2357.     RSP_LINE("E", handle_e, response_type_normal, rs_essential),
  2358.     /* Possibly should be response_type_error.  */
  2359.     RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
  2360.  
  2361. #undef RSP_LINE
  2362. };
  2363.  
  2364. #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
  2365. #ifdef CLIENT_SUPPORT
  2366.  
  2367. /* 
  2368.  * If LEN is 0, then send_to_server() computes string's length itself.
  2369.  *
  2370.  * Therefore, pass the real length when transmitting data that might
  2371.  * contain 0's.
  2372.  */
  2373. void
  2374. send_to_server (str, len)
  2375.      char *str;
  2376.      size_t len;
  2377. {
  2378.   if (len == 0)
  2379.     len = strlen (str);
  2380.   
  2381. #ifdef NO_SOCKET_TO_FD
  2382.   if (use_socket_style)
  2383.     {
  2384.       int just_wrtn = 0;
  2385.       size_t wrtn = 0;
  2386.  
  2387. #ifdef VMS
  2388.       /* send() blocks under VMS */
  2389.       if (send (server_sock, str + wrtn, len - wrtn, 0) < 0)
  2390.         error (1, errno, "writing to server socket");
  2391. #else /* VMS */
  2392.       while (wrtn < len)
  2393.         {
  2394.           just_wrtn = send (server_sock, str + wrtn, len - wrtn, 0);
  2395.  
  2396.           if (just_wrtn == -1)
  2397.             error (1, errno, "writing to server socket");
  2398.           
  2399.           wrtn += just_wrtn;
  2400.           if (wrtn == len)
  2401.             break;
  2402.         }
  2403. #endif  /* VMS */
  2404.     }
  2405.   else
  2406. #endif /* NO_SOCKET_TO_FD */
  2407.     {
  2408.       size_t wrtn = 0;
  2409.       
  2410.       while (wrtn < len)
  2411.         {
  2412.           wrtn += fwrite (str + wrtn, 1, len - wrtn, to_server);
  2413.           
  2414.           if (wrtn == len)
  2415.             break;
  2416.           
  2417.           if (ferror (to_server))
  2418.             error (1, errno, "writing to server");
  2419.           if (feof (to_server))
  2420.             error (1, 0, "premature end-of-file on server");
  2421.         }
  2422.     }
  2423.       
  2424.   if (to_server_logfile)
  2425.     if (fwrite (str, 1, len, to_server_logfile) < len)
  2426.       error (0, errno, "writing to to-server logfile");
  2427. }
  2428.  
  2429. /* Read up to LEN bytes from the server.  Returns actual number of bytes
  2430.    read.  Gives a fatal error on EOF or error.  */
  2431. static size_t
  2432. try_read_from_server (buf, len)
  2433.     char *buf;
  2434.     size_t len;
  2435. {
  2436.     int nread;
  2437.  
  2438. #ifdef NO_SOCKET_TO_FD
  2439.     if (use_socket_style)
  2440.     {
  2441.     nread = recv (server_sock, buf, len, 0);
  2442.     if (nread == -1)
  2443.         error (1, errno, "reading from server");
  2444.     }
  2445.     else
  2446. #endif
  2447.     {
  2448.     nread = fread (buf, 1, len, from_server);
  2449.     if (ferror (from_server))
  2450.         error (1, errno, "reading from server");
  2451.     if (feof (from_server))
  2452.         error (1, 0,
  2453.            "end of file from server (consult above messages if any)");
  2454.     }
  2455.  
  2456.     /* Log, if that's what we're doing. */
  2457.     if (from_server_logfile != NULL && nread > 0)
  2458.     {
  2459.     size_t towrite = nread;
  2460.     if (fwrite (buf, 1, towrite, from_server_logfile) < towrite)
  2461.         error (0, errno, "writing to from-server logfile");
  2462.     }
  2463.  
  2464.     return nread;
  2465. }
  2466.  
  2467. /*
  2468.  * Read LEN bytes from the server or die trying.
  2469.  */
  2470. void
  2471. read_from_server (buf, len)
  2472.     char *buf;
  2473.     size_t len;
  2474. {
  2475.     size_t red = 0;
  2476.     while (red < len)
  2477.     {
  2478.     red += try_read_from_server (buf + red, len - red);
  2479.     if (red == len)
  2480.         break;
  2481.     }
  2482. }
  2483.  
  2484. /*
  2485.  * Get some server responses and process them.  Returns nonzero for
  2486.  * error, 0 for success.  */
  2487. int
  2488. get_server_responses ()
  2489. {
  2490.     struct response *rs;
  2491.     do
  2492.     {
  2493.     char *cmd;
  2494.     int len;
  2495.     
  2496.     len = read_line (&cmd, 0);
  2497.     for (rs = responses; rs->name != NULL; ++rs)
  2498.         if (strncmp (cmd, rs->name, strlen (rs->name)) == 0)
  2499.         {
  2500.         int cmdlen = strlen (rs->name);
  2501.         if (cmd[cmdlen] == '\0')
  2502.             ;
  2503.         else if (cmd[cmdlen] == ' ')
  2504.             ++cmdlen;
  2505.         else
  2506.             /*
  2507.              * The first len characters match, but it's a different
  2508.              * response.  e.g. the response is "oklahoma" but we
  2509.              * matched "ok".
  2510.              */
  2511.             continue;
  2512.         (*rs->func) (cmd + cmdlen, len - cmdlen);
  2513.         break;
  2514.         }
  2515.     if (rs->name == NULL)
  2516.         /* It's OK to print just to the first '\0'.  */
  2517.         error (0, 0,
  2518.            "warning: unrecognized response `%s' from cvs server",
  2519.            cmd);
  2520.     free (cmd);
  2521.     } while (rs->type == response_type_normal);
  2522.     return rs->type == response_type_error ? 1 : 0;
  2523. }
  2524.  
  2525. /* Get the responses and then close the connection.  */
  2526. int server_fd = -1;
  2527.  
  2528. /*
  2529.  * Flag var; we'll set it in start_server() and not one of its
  2530.  * callees, such as start_rsh_server().  This means that there might
  2531.  * be a small window between the starting of the server and the
  2532.  * setting of this var, but all the code in that window shouldn't care
  2533.  * because it's busy checking return values to see if the server got
  2534.  * started successfully anyway.
  2535.  */
  2536. int server_started = 0;
  2537.  
  2538. int
  2539. get_responses_and_close ()
  2540. {
  2541.     int errs = get_server_responses ();
  2542.  
  2543.     do_deferred_progs ();
  2544.  
  2545.     if (client_prune_dirs)
  2546.     process_prune_candidates ();
  2547.  
  2548. #ifdef NO_SOCKET_TO_FD
  2549.     if (use_socket_style)
  2550.       {
  2551.         if (shutdown (server_sock, 2) < 0)
  2552.           error (1, errno, "shutting down server socket");
  2553.       }
  2554.     else
  2555. #endif /* NO_SOCKET_TO_FD */
  2556.       {
  2557. #if defined(HAVE_KERBEROS) || defined(USE_DIRECT_TCP) || defined(AUTH_CLIENT_SUPPORT)
  2558.         if (server_fd != -1)
  2559.           {
  2560.             if (shutdown (server_fd, 1) < 0)
  2561.               error (1, errno, "shutting down connection to %s", server_host);
  2562.             /*
  2563.              * This test will always be true because we dup the descriptor
  2564.              */
  2565.             if (fileno (from_server) != fileno (to_server))
  2566.               {
  2567.                 if (fclose (to_server) != 0)
  2568.                   error (1, errno,
  2569.                          "closing down connection to %s",
  2570.                          server_host);
  2571.               }
  2572.           }
  2573.         else
  2574. #endif /* HAVE_KERBEROS || USE_DIRECT_TCP || AUTH_CLIENT_SUPPORT */
  2575.           
  2576. #ifdef SHUTDOWN_SERVER
  2577.           SHUTDOWN_SERVER (fileno (to_server));
  2578. #else /* ! SHUTDOWN_SERVER */
  2579.         {
  2580.           
  2581. #ifdef START_RSH_WITH_POPEN_RW
  2582.           if (pclose (to_server) == EOF)
  2583. #else /* ! START_RSH_WITH_POPEN_RW */
  2584.             if (fclose (to_server) == EOF)
  2585. #endif /* START_RSH_WITH_POPEN_RW */
  2586.               {
  2587.                 error (1, errno, "closing connection to %s", server_host);
  2588.               }
  2589.         }
  2590.  
  2591.         if (getc (from_server) != EOF)
  2592.           error (0, 0, "dying gasps from %s unexpected", server_host);
  2593.         else if (ferror (from_server))
  2594.           error (0, errno, "reading from %s", server_host);
  2595.         
  2596.         fclose (from_server);
  2597. #endif /* SHUTDOWN_SERVER */
  2598.       }
  2599.         
  2600. #if ! RSH_NOT_TRANSPARENT
  2601.     if (rsh_pid != -1
  2602.     && waitpid (rsh_pid, (int *) 0, 0) == -1)
  2603.     error (1, errno, "waiting for process %d", rsh_pid);
  2604. #endif /* ! RSH_NOT_TRANSPARENT */
  2605.  
  2606.     server_started = 0;
  2607.  
  2608.     return errs;
  2609. }
  2610.     
  2611. #ifndef RSH_NOT_TRANSPARENT
  2612. static void start_rsh_server PROTO((int *, int *));
  2613. #endif /* RSH_NOT_TRANSPARENT */
  2614.  
  2615. int
  2616. supported_request (name)
  2617.      char *name;
  2618. {
  2619.   struct request *rq;
  2620.  
  2621.   for (rq = requests; rq->name; rq++)
  2622.     if (!strcmp (rq->name, name))
  2623.       return rq->status == rq_supported;
  2624.   error (1, 0, "internal error: testing support for unknown option?");
  2625.   /* NOTREACHED */
  2626.   return 0;
  2627. }
  2628.  
  2629.  
  2630. #ifdef AUTH_CLIENT_SUPPORT
  2631. void
  2632. init_sockaddr (name, hostname, port)
  2633.     struct sockaddr_in *name;
  2634.     const char *hostname;
  2635.     unsigned short int port;
  2636. {
  2637.     struct hostent *hostinfo;
  2638.  
  2639.     memset (name, 0, sizeof (*name));
  2640.     name->sin_family = AF_INET;
  2641.     name->sin_port = htons (port);
  2642.     hostinfo = gethostbyname (hostname);
  2643.     if (hostinfo == NULL)
  2644.     {
  2645.     fprintf (stderr, "Unknown host %s.\n", hostname);
  2646.     exit (EXIT_FAILURE);
  2647.     }
  2648.     name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
  2649. }
  2650.  
  2651.  
  2652. int
  2653. auth_server_port_number ()
  2654. {
  2655.   return CVS_AUTH_PORT;
  2656. }
  2657.  
  2658.  
  2659. /*
  2660.  * Connect to the authenticating server.
  2661.  *
  2662.  * If VERIFY_ONLY is non-zero, then just verify that the password is
  2663.  * correct and then shutdown the connection.  In this case, the return
  2664.  * values is 1 if the password was correct, 0 if not.
  2665.  *
  2666.  * If VERIFY_ONLY is 0, then really connect to the server.  In this
  2667.  * case the return value is 1 on succees, but is probably ignored.  If
  2668.  * fail to connect, then die with error.
  2669.  */
  2670. int
  2671. connect_to_pserver (tofdp, fromfdp, verify_only)
  2672.      int *tofdp, *fromfdp;
  2673.      int verify_only;
  2674. {
  2675.     int sock;
  2676. #ifndef NO_SOCKET_TO_FD
  2677.     int tofd, fromfd;
  2678. #endif
  2679.     int port_number;
  2680.     struct sockaddr_in client_sai;
  2681.  
  2682.     /* Does nothing if already called before now. */
  2683.     parse_cvsroot ();
  2684.  
  2685.     sock = socket (AF_INET, SOCK_STREAM, 0);
  2686.     if (sock == -1)
  2687.     {
  2688.     fprintf (stderr, "socket() failed\n");
  2689.     exit (EXIT_FAILURE);
  2690.     }
  2691.     port_number = auth_server_port_number ();
  2692.     init_sockaddr (&client_sai, server_host, port_number);
  2693.     if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
  2694.     < 0)
  2695.     error (1, errno, "connect to %s:%d failed", server_host,
  2696.            CVS_AUTH_PORT);
  2697.  
  2698.     /* Run the authorization mini-protocol before anything else. */
  2699.     {
  2700.     int i;
  2701.     char ch, read_buf[PATH_MAX];
  2702.     char *begin      = NULL;
  2703.     char *repository = server_cvsroot;
  2704.     char *username   = server_user;
  2705.     char *password   = NULL;
  2706.     char *end        = NULL;
  2707.  
  2708.     if (verify_only)
  2709.     {
  2710.         begin = "BEGIN VERIFICATION REQUEST\n";
  2711.         end   = "END VERIFICATION REQUEST\n";
  2712.     }
  2713.     else
  2714.     {
  2715.         begin = "BEGIN AUTH REQUEST\n";
  2716.         end   = "END AUTH REQUEST\n";
  2717.     }
  2718.  
  2719.     /* Get the password, probably from ~/.cvspass. */
  2720.     password = get_cvs_password (server_user, server_host, server_cvsroot);
  2721.  
  2722.     /* Announce that we're starting the authorization protocol. */
  2723.     send (sock, begin, strlen (begin), 0);
  2724.  
  2725.     /* Send the data the server needs. */
  2726.     send (sock, repository, strlen (repository), 0);
  2727.     send (sock, "\n", 1, 0);
  2728.     send (sock, username, strlen (username), 0);
  2729.     send (sock, "\n", 1, 0);
  2730.     send (sock, password, strlen (password), 0);
  2731.     send (sock, "\n", 1, 0);
  2732.  
  2733.     /* Announce that we're ending the authorization protocol. */
  2734.     send (sock, end, strlen (end), 0);
  2735.  
  2736.     /* Paranoia. */
  2737.     memset (password, 0, strlen (password));
  2738.  
  2739.     /* Get ACK or NACK from the server. 
  2740.      * 
  2741.      * We could avoid this careful read-char loop by having the ACK
  2742.      * and NACK cookies be of the same length, so we'd simply read
  2743.      * that length and see what we got.  But then there'd be Yet
  2744.      * Another Protocol Requirement floating around, and someday
  2745.      * someone would make a change that breaks it and spend a hellish
  2746.      * day tracking it down.  Therefore, we use "\n" to mark off the
  2747.      * end of both ACK and NACK, and we loop, reading until "\n".
  2748.      */
  2749.     ch = 0;
  2750.     memset (read_buf, 0, PATH_MAX);
  2751.     for (i = 0; (i < (PATH_MAX - 1)) && (ch != '\n'); i++)
  2752.     {
  2753.         if (recv (sock, &ch, 1, 0) < 0)
  2754.                 error (1, errno, "recv() from server %s", server_host);
  2755.  
  2756.             read_buf[i] = ch;
  2757.     }
  2758.  
  2759.     if (strcmp (read_buf, "I HATE YOU\n") == 0)
  2760.     {
  2761.         /* Authorization not granted. */
  2762.         if (shutdown (sock, 2) < 0)
  2763.         {
  2764.         error (0, 0, 
  2765.                "authorization failed: server %s rejected access", 
  2766.                server_host);
  2767.         error (1, errno,
  2768.                "shutdown() failed (server %s)", server_host);
  2769.         }
  2770.  
  2771.         if (verify_only)
  2772.         return 0;
  2773.         else
  2774.         error (1, 0, 
  2775.                "authorization failed: server %s rejected access", 
  2776.                server_host);
  2777.     }
  2778.     else if (strcmp (read_buf, "I LOVE YOU\n") != 0)
  2779.     {
  2780.         /* Unrecognized response from server. */
  2781.         if (shutdown (sock, 2) < 0)
  2782.         {
  2783.         error (0, 0,
  2784.                "unrecognized auth response from %s: %s", 
  2785.                server_host, read_buf);
  2786.         error (1, errno, "shutdown() failed, server %s", server_host);
  2787.         }
  2788.         error (1, 0, 
  2789.            "unrecognized auth response from %s: %s", 
  2790.            server_host, read_buf);
  2791.     }
  2792.     }
  2793.  
  2794.     if (verify_only)
  2795.     {
  2796.     if (shutdown (sock, 2) < 0)
  2797.         error (0, errno, "shutdown() failed, server %s", server_host);
  2798.     return 1;
  2799.     }
  2800.     else
  2801.     {
  2802. #ifdef NO_SOCKET_TO_FD
  2803.     use_socket_style = 1;
  2804.     server_sock = sock;
  2805.     /* Try to break mistaken callers: */
  2806.     *tofdp = 0;
  2807.     *fromfdp = 0;
  2808. #else /* ! NO_SOCKET_TO_FD */
  2809.     server_fd = sock;
  2810.     close_on_exec (server_fd);
  2811.     tofd = fromfd = sock;
  2812.     /* Hand them back to the caller. */
  2813.     *tofdp   = tofd;
  2814.     *fromfdp = fromfd;
  2815. #endif /* NO_SOCKET_TO_FD */
  2816.     }
  2817.  
  2818.     return 1;
  2819. }
  2820. #endif /* AUTH_CLIENT_SUPPORT */
  2821.  
  2822.  
  2823. #if HAVE_KERBEROS || USE_DIRECT_TCP
  2824.  
  2825. /*
  2826.  * FIXME: this function has not been changed to deal with
  2827.  * NO_SOCKET_TO_FD (i.e., systems on which sockets cannot be converted
  2828.  * to file descriptors.  The first person to try building a kerberos
  2829.  * client on such a system (OS/2, Windows 95, and maybe others) will
  2830.  * have to make take care of this.
  2831.  */
  2832. void
  2833. start_tcp_server (tofdp, fromfdp)
  2834.      int *tofdp, *fromfdp;
  2835. {
  2836.   int tofd, fromfd;
  2837.  
  2838.   struct hostent *hp;
  2839.   char *hname;
  2840.   const char *portenv;
  2841.   int port;
  2842.   struct sockaddr_in sin;
  2843.   int s;
  2844.  
  2845.  
  2846. #if HAVE_KERBEROS
  2847.   KTEXT_ST ticket;
  2848.   const char *realm;
  2849. #endif /* HAVE_KERBEROS */
  2850.  
  2851.   int status;
  2852.   
  2853.   /*
  2854.    * We look up the host to give a better error message if it
  2855.    * does not exist.  However, we then pass server_host to
  2856.    * krb_sendauth, rather than the canonical name, because
  2857.    * krb_sendauth is going to do its own canonicalization anyhow
  2858.    * and that lets us not worry about the static storage used by
  2859.    * gethostbyname.
  2860.    */
  2861.   hp = gethostbyname (server_host);
  2862.   if (hp == NULL)
  2863.     error (1, 0, "%s: unknown host", server_host);
  2864.   hname = xmalloc (strlen (hp->h_name) + 1);
  2865.   strcpy (hname, hp->h_name);
  2866.   
  2867. #if HAVE_KERBEROS
  2868.   realm = krb_realmofhost (hname);
  2869. #endif /* HAVE_KERBEROS */
  2870.   
  2871.   /* Get CVS_CLIENT_PORT or look up cvs/tcp with CVS_PORT as default */
  2872.   portenv = getenv ("CVS_CLIENT_PORT");
  2873.   if (portenv != NULL)
  2874.     {
  2875.       port = atoi (portenv);
  2876.       if (port <= 0)
  2877.         goto try_rsh_no_message;
  2878.       if (trace)
  2879.         fprintf(stderr, "Using TCP port %d to contact server.\n", port);
  2880.       port = htons (port);
  2881.     }
  2882.   else
  2883.     {
  2884.       struct servent *sp;
  2885.       
  2886.       sp = getservbyname ("cvs", "tcp");
  2887.       if (sp == NULL)
  2888.         port = htons (CVS_PORT);
  2889.       else
  2890.         port = sp->s_port;
  2891.     }
  2892.   
  2893.   s = socket (AF_INET, SOCK_STREAM, 0);
  2894.   if (s < 0)
  2895.     error (1, errno, "socket");
  2896.   
  2897.   memset (&sin, 0, sizeof sin);
  2898.   sin.sin_family = AF_INET;
  2899.   sin.sin_addr.s_addr = INADDR_ANY;
  2900.   sin.sin_port = 0;
  2901.   
  2902.   if (bind (s, (struct sockaddr *) &sin, sizeof sin) < 0)
  2903.     error (1, errno, "bind");
  2904.   
  2905.   memcpy (&sin.sin_addr, hp->h_addr, hp->h_length);
  2906.   sin.sin_port = port;
  2907.   
  2908.   tofd = -1;
  2909.   if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
  2910.     {
  2911.       error (0, errno, "connect");
  2912.       close (s);
  2913.     }
  2914.   else
  2915.     {
  2916. #ifdef HAVE_KERBEROS
  2917.       struct sockaddr_in laddr;
  2918.       int laddrlen;
  2919.       MSG_DAT msg_data;
  2920.       CREDENTIALS cred;
  2921.       Key_schedule sched;
  2922.       
  2923.       laddrlen = sizeof (laddr);
  2924.       if (getsockname (s, (struct sockaddr *) &laddr, &laddrlen) < 0)
  2925.         error (1, errno, "getsockname");
  2926.       
  2927.       /* We don't care about the checksum, and pass it as zero.  */
  2928.       status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd",
  2929.                              hname, realm, (unsigned long) 0, &msg_data,
  2930.                              &cred, sched, &laddr, &sin, "KCVSV1.0");
  2931.       if (status != KSUCCESS)
  2932.         {
  2933.           error (0, 0, "kerberos: %s", krb_get_err_text(status));
  2934.           close (s);
  2935.         }
  2936.       else
  2937.         {
  2938. #endif /* HAVE_KERBEROS */
  2939.  
  2940.           server_fd = s;
  2941.           close_on_exec (server_fd);
  2942.           tofd = fromfd = s;
  2943.  
  2944. #ifdef HAVE_KERBEROS
  2945.         }
  2946. #endif /* HAVE_KERBEROS */
  2947.     }
  2948.   
  2949.   if (tofd == -1)
  2950.     {
  2951.       /* FIXME: Falling back like this is slow and we should probably
  2952.      just make it a fatal error (so that people use the right
  2953.      environment variables or, when we get around to implementing
  2954.      the right ones, access methods).  */
  2955.       error (0, 0, "trying to start server using rsh");
  2956.     try_rsh_no_message:
  2957.       server_fd = -1;
  2958. #if ! RSH_NOT_TRANSPARENT
  2959.       start_rsh_server (&tofd, &fromfd);
  2960. #else /* RSH_NOT_TRANSPARENT */
  2961. #if defined (START_SERVER)
  2962.       START_SERVER (&tofd, &fromfd, getcaller (),
  2963.                     server_user, server_host, server_cvsroot);
  2964. #endif /* defined (START_SERVER) */
  2965. #endif /* ! RSH_NOT_TRANSPARENT */
  2966.     }
  2967.   free (hname);
  2968.  
  2969.   /* Give caller the values it wants. */
  2970.   *tofdp   = tofd;
  2971.   *fromfdp = fromfd;
  2972. }
  2973.  
  2974. #endif /* HAVE_KERBEROS || USE_DIRECT_TCP */
  2975.  
  2976. static int send_variable_proc PROTO ((Node *, void *));
  2977.  
  2978. static int
  2979. send_variable_proc (node, closure)
  2980.     Node *node;
  2981.     void *closure;
  2982. {
  2983.     send_to_server ("Set ", 0);
  2984.     send_to_server (node->key, 0);
  2985.     send_to_server ("=", 1);
  2986.     send_to_server (node->data, 0);
  2987.     send_to_server ("\012", 1);
  2988.     return 0;
  2989. }
  2990.  
  2991. /* Contact the server.  */
  2992. void
  2993. start_server ()
  2994. {
  2995.   int tofd, fromfd;
  2996.   char *log = getenv ("CVS_CLIENT_LOG");
  2997.  
  2998.   /* Note that generally speaking we do *not* fall back to a different
  2999.      way of connecting if the first one does not work.  This is slow
  3000.      (*really* slow on a 14.4kbps link); the clean way to have a CVS
  3001.      which supports several ways of connecting is with access methods.  */
  3002.  
  3003.   /* Init these to NULL.  They will be set later if logging is on. */
  3004.   from_server_logfile = (FILE *) NULL;
  3005.   to_server_logfile   = (FILE *) NULL;
  3006.  
  3007. #ifdef AUTH_CLIENT_SUPPORT
  3008.     if (use_authenticating_server)
  3009.       {
  3010.         /* Toss the return value.  It will die with error if anything
  3011.            goes wrong anyway. */
  3012.         connect_to_pserver (&tofd, &fromfd, 0);
  3013.       }
  3014.     else
  3015. #endif /* AUTH_CLIENT_SUPPORT */
  3016.       {
  3017. #if HAVE_KERBEROS || USE_DIRECT_TCP
  3018.         start_tcp_server (&tofd, &fromfd);
  3019. #else
  3020.  
  3021. #  if ! RSH_NOT_TRANSPARENT
  3022.         start_rsh_server (&tofd, &fromfd);
  3023. #  else
  3024.  
  3025. #    if defined(START_SERVER)
  3026.         START_SERVER (&tofd, &fromfd, getcaller (),
  3027.                       server_user, server_host, server_cvsroot);
  3028. #    endif
  3029. #  endif
  3030. #endif
  3031.       }
  3032.  
  3033. #if defined(VMS) && defined(NO_SOCKET_TO_FD)
  3034.     /* Avoid mixing sockets with stdio */
  3035.     use_socket_style = 1;
  3036.     server_sock = tofd;
  3037. #endif /* VMS && NO_SOCKET_TO_FD */
  3038.  
  3039.     /* "Hi, I'm Darlene and I'll be your server tonight..." */
  3040.     server_started = 1;
  3041.  
  3042.     /* Set up logfiles, if any. */
  3043.     if (log)
  3044.     {
  3045.     int len = strlen (log);
  3046.     char *buf = xmalloc (len + 5);
  3047.     char *p;
  3048.  
  3049.     strcpy (buf, log);
  3050.     p = buf + len;
  3051.  
  3052.     strcpy (p, ".in");
  3053.     to_server_logfile = open_file (buf, "w");
  3054.         if (to_server_logfile == NULL)
  3055.           error (0, errno, "opening to-server logfile %s", buf);
  3056.  
  3057.     strcpy (p, ".out");
  3058.     from_server_logfile = open_file (buf, "w");
  3059.         if (from_server_logfile == NULL)
  3060.           error (0, errno, "opening from-server logfile %s", buf);
  3061.  
  3062.     free (buf);
  3063.     }
  3064.  
  3065. #ifdef NO_SOCKET_TO_FD
  3066.     if (! use_socket_style)
  3067. #endif /* NO_SOCKET_TO_FD */
  3068.       {
  3069.         /* todo: some OS's don't need these calls... */
  3070.         close_on_exec (tofd);
  3071.         close_on_exec (fromfd);
  3072.  
  3073.     /* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
  3074.        fdopening the same file descriptor twice, so dup it if it is the
  3075.        same.  */
  3076.     if (tofd == fromfd)
  3077.     {
  3078.         fromfd = dup (tofd);
  3079.         if (fromfd < 0)
  3080.         error (1, errno, "cannot dup net connection");
  3081.     }
  3082.  
  3083.         /* These will use binary mode on systems which have it.  */
  3084.         to_server = fdopen (tofd, FOPEN_BINARY_WRITE);
  3085.         if (to_server == NULL)
  3086.           error (1, errno, "cannot fdopen %d for write", tofd);
  3087.         from_server = fdopen (fromfd, FOPEN_BINARY_READ);
  3088.         if (from_server == NULL)
  3089.           error (1, errno, "cannot fdopen %d for read", fromfd);
  3090.       }
  3091.  
  3092.     /* Clear static variables.  */
  3093.     if (toplevel_repos != NULL)
  3094.         free (toplevel_repos);
  3095.     toplevel_repos = NULL;
  3096.     if (last_dir_name != NULL)
  3097.         free (last_dir_name);
  3098.     last_dir_name = NULL;
  3099.     if (last_repos != NULL)
  3100.         free (last_repos);
  3101.     last_repos = NULL;
  3102.     if (last_update_dir != NULL)
  3103.         free (last_update_dir);
  3104.     last_update_dir = NULL;
  3105.     stored_checksum_valid = 0;
  3106.     stored_mode_valid = 0;
  3107.  
  3108.     if (strcmp (command_name, "init") != 0)
  3109.     {
  3110.     send_to_server ("Root ", 0);
  3111.     send_to_server (server_cvsroot, 0);
  3112.     send_to_server ("\012", 1);
  3113.     }
  3114.  
  3115.     {
  3116.     struct response *rs;
  3117.  
  3118.     send_to_server ("Valid-responses", 0);
  3119.  
  3120.     for (rs = responses; rs->name != NULL; ++rs)
  3121.     {
  3122.         send_to_server (" ", 0);
  3123.         send_to_server (rs->name, 0);
  3124.     }
  3125.     send_to_server ("\012", 1);
  3126.     }
  3127.     send_to_server ("valid-requests\012", 0);
  3128.  
  3129.     if (get_server_responses ())
  3130.     exit (EXIT_FAILURE);
  3131.  
  3132.     /*
  3133.      * Now handle global options.
  3134.      *
  3135.      * -H, -f, -d, -e should be handled OK locally.
  3136.      *
  3137.      * -b we ignore (treating it as a server installation issue).
  3138.      * FIXME: should be an error message.
  3139.      *
  3140.      * -v we print local version info; FIXME: Add a protocol request to get
  3141.      * the version from the server so we can print that too.
  3142.      *
  3143.      * -l -t -r -w -q -n and -Q need to go to the server.
  3144.      */
  3145.  
  3146.     {
  3147.     int have_global = supported_request ("Global_option");
  3148.  
  3149.     if (noexec)
  3150.     {
  3151.         if (have_global)
  3152.         {
  3153.         send_to_server ("Global_option -n\012", 0);
  3154.         }
  3155.         else
  3156.         error (1, 0,
  3157.                "This server does not support the global -n option.");
  3158.     }
  3159.     if (quiet)
  3160.     {
  3161.         if (have_global)
  3162.         {
  3163.         send_to_server ("Global_option -q\012", 0);
  3164.         }
  3165.         else
  3166.         error (1, 0,
  3167.                "This server does not support the global -q option.");
  3168.     }
  3169.     if (really_quiet)
  3170.     {
  3171.         if (have_global)
  3172.         {
  3173.         send_to_server ("Global_option -Q\012", 0);
  3174.         }
  3175.         else
  3176.         error (1, 0,
  3177.                "This server does not support the global -Q option.");
  3178.     }
  3179.     if (!cvswrite)
  3180.     {
  3181.         if (have_global)
  3182.         {
  3183.         send_to_server ("Global_option -r\012", 0);
  3184.         }
  3185.         else
  3186.         error (1, 0,
  3187.                "This server does not support the global -r option.");
  3188.     }
  3189.     if (trace)
  3190.     {
  3191.         if (have_global)
  3192.         {
  3193.         send_to_server ("Global_option -t\012", 0);
  3194.         }
  3195.         else
  3196.         error (1, 0,
  3197.                "This server does not support the global -t option.");
  3198.     }
  3199.     if (logoff)
  3200.     {
  3201.         if (have_global)
  3202.         {
  3203.         send_to_server ("Global_option -l\012", 0);
  3204.         }
  3205.         else
  3206.         error (1, 0,
  3207.                "This server does not support the global -l option.");
  3208.     }
  3209.     }
  3210.     if (gzip_level)
  3211.     {
  3212.     if (supported_request ("gzip-file-contents"))
  3213.     {
  3214.             char gzip_level_buf[5];
  3215.         send_to_server ("gzip-file-contents ", 0);
  3216.             sprintf (gzip_level_buf, "%d", gzip_level);
  3217.         send_to_server (gzip_level_buf, 0);
  3218.  
  3219.         send_to_server ("\012", 1);
  3220.     }
  3221.     else
  3222.     {
  3223.         fprintf (stderr, "server doesn't support gzip-file-contents\n");
  3224.         gzip_level = 0;
  3225.     }
  3226.     }
  3227.  
  3228. #ifdef FILENAMES_CASE_INSENSITIVE
  3229.     if (supported_request ("Case"))
  3230.     send_to_server ("Case\012", 0);
  3231. #endif
  3232.  
  3233.     /* If "Set" is not supported, just silently fail to send the variables.
  3234.        Users with an old server should get a useful error message when it
  3235.        fails to recognize the ${=foo} syntax.  This way if someone uses
  3236.        several servers, some of which are new and some old, they can still
  3237.        set user variables in their .cvsrc without trouble.  */
  3238.     if (supported_request ("Set"))
  3239.     walklist (variable_list, send_variable_proc, NULL);
  3240. }
  3241.  
  3242. #ifndef RSH_NOT_TRANSPARENT
  3243. /* Contact the server by starting it with rsh.  */
  3244.  
  3245. /* Right now, we have two different definitions for this function,
  3246.    depending on whether we start the rsh server using popenRW or not.
  3247.    This isn't ideal, and the best thing would probably be to change
  3248.    the OS/2 port to be more like the regular Unix client (i.e., by
  3249.    implementing piped_child)... but I'm doing something else at the
  3250.    moment, and wish to make only one change at a time.  -Karl */
  3251.  
  3252. #ifdef START_RSH_WITH_POPEN_RW
  3253.  
  3254. /* This is actually a crock -- it's OS/2-specific, for no one else
  3255.    uses it.  If I get time, I want to make piped_child and all the
  3256.    other stuff in os2/run.c work right.  In the meantime, this gets us
  3257.    up and running, and that's most important. */
  3258.  
  3259. static void
  3260. start_rsh_server (tofdp, fromfdp)
  3261.      int *tofdp, *fromfdp;
  3262. {
  3263.   int pipes[2];
  3264.   
  3265.   /* If you're working through firewalls, you can set the
  3266.      CVS_RSH environment variable to a script which uses rsh to
  3267.      invoke another rsh on a proxy machine.  */
  3268.   char *cvs_rsh = getenv ("CVS_RSH");
  3269.   char *cvs_server = getenv ("CVS_SERVER");
  3270.   char command[PATH_MAX];
  3271.   int i = 0;
  3272.   /* This needs to fit "rsh", "-b", "-l", "USER", "host",
  3273.      "cmd (w/ args)", and NULL.  We leave some room to grow. */
  3274.   char *rsh_argv[10];
  3275.   
  3276.   if (!cvs_rsh)
  3277.     cvs_rsh = "rsh";
  3278.   if (!cvs_server)
  3279.     cvs_server = "cvs";
  3280.   
  3281.   /* If you are running a very old (Nov 3, 1994, before 1.5)
  3282.    * version of the server, you need to make sure that your .bashrc
  3283.    * on the server machine does not set CVSROOT to something
  3284.    * containing a colon (or better yet, upgrade the server).  */
  3285.   
  3286.   /* The command line starts out with rsh. */
  3287.   rsh_argv[i++] = cvs_rsh;
  3288.   
  3289. #ifdef RSH_NEEDS_BINARY_FLAG
  3290.   /* "-b" for binary, under OS/2. */
  3291.   rsh_argv[i++] = "-b";
  3292. #endif /* RSH_NEEDS_BINARY_FLAG */
  3293.  
  3294.   /* Then we strcat more things on the end one by one. */
  3295.   if (server_user != NULL)
  3296.     {
  3297.       rsh_argv[i++] = "-l";
  3298.       rsh_argv[i++] = server_user;
  3299.     }
  3300.   
  3301.   rsh_argv[i++] = server_host;
  3302.   rsh_argv[i++] = cvs_server;
  3303.   rsh_argv[i++] = "server";
  3304.  
  3305.   /* Mark the end of the arg list. */
  3306.   rsh_argv[i]   = (char *) NULL;
  3307.  
  3308.   if (trace)
  3309.     {
  3310.       fprintf (stderr, " -> Starting server: ");
  3311.       fprintf (stderr, "%s", command);
  3312.       putc ('\n', stderr);
  3313.     }
  3314.   
  3315.   /* Do the deed. */
  3316.   rsh_pid = popenRW (rsh_argv, pipes);
  3317.   if (rsh_pid < 0)
  3318.     error (1, errno, "cannot start server via rsh");
  3319.  
  3320.   /* Give caller the file descriptors. */
  3321.   *tofdp   = pipes[0];
  3322.   *fromfdp = pipes[1];
  3323. }
  3324.  
  3325. #else /* ! START_RSH_WITH_POPEN_RW */
  3326.  
  3327. static void
  3328. start_rsh_server (tofdp, fromfdp)
  3329.      int *tofdp;
  3330.      int *fromfdp;
  3331. {
  3332.     /* If you're working through firewalls, you can set the
  3333.        CVS_RSH environment variable to a script which uses rsh to
  3334.        invoke another rsh on a proxy machine.  */
  3335.     char *cvs_rsh = getenv ("CVS_RSH");
  3336.     char *cvs_server = getenv ("CVS_SERVER");
  3337.     char *command;
  3338.  
  3339.     if (!cvs_rsh)
  3340.     cvs_rsh = "rsh";
  3341.     if (!cvs_server)
  3342.     cvs_server = "cvs";
  3343.  
  3344.     /* Pass the command to rsh as a single string.  This shouldn't
  3345.        affect most rsh servers at all, and will pacify some buggy
  3346.        versions of rsh that grab switches out of the middle of the
  3347.        command (they're calling the GNU getopt routines incorrectly).  */
  3348.     command = xmalloc (strlen (cvs_server)
  3349.                + strlen (server_cvsroot)
  3350.                + 50);
  3351.  
  3352.     /* If you are running a very old (Nov 3, 1994, before 1.5)
  3353.      * version of the server, you need to make sure that your .bashrc
  3354.      * on the server machine does not set CVSROOT to something
  3355.      * containing a colon (or better yet, upgrade the server).  */
  3356.     sprintf (command, "%s server", cvs_server);
  3357.  
  3358.     {
  3359.         char *argv[10];
  3360.     char **p = argv;
  3361.  
  3362.     *p++ = cvs_rsh;
  3363.     *p++ = server_host;
  3364.  
  3365.     /* If the login names differ between client and server
  3366.      * pass it on to rsh.
  3367.      */
  3368.     if (server_user != NULL)
  3369.     {
  3370.         *p++ = "-l";
  3371.         *p++ = server_user;
  3372.     }
  3373.  
  3374.     *p++ = command;
  3375.     *p++ = NULL;
  3376.  
  3377.     if (trace)
  3378.         {
  3379.         int i;
  3380.  
  3381.             fprintf (stderr, " -> Starting server: ");
  3382.         for (i = 0; argv[i]; i++)
  3383.             fprintf (stderr, "%s ", argv[i]);
  3384.         putc ('\n', stderr);
  3385.     }
  3386.     rsh_pid = piped_child (argv, tofdp, fromfdp);
  3387.  
  3388.     if (rsh_pid < 0)
  3389.         error (1, errno, "cannot start server via rsh");
  3390.     }
  3391. }
  3392.  
  3393. #endif /* START_RSH_WITH_POPEN_RW */
  3394. #endif /* ! RSH_NOT_TRANSPARENT */
  3395.  
  3396.  
  3397.  
  3398. /* Send an argument STRING.  */
  3399. void
  3400. send_arg (string)
  3401.     char *string;
  3402. {
  3403.     char buf[1];
  3404.     char *p = string;
  3405.  
  3406.     send_to_server ("Argument ", 0);
  3407.  
  3408.     while (*p)
  3409.     {
  3410.     if (*p == '\n')
  3411.     {
  3412.         send_to_server ("\012Argumentx ", 0);
  3413.     }
  3414.     else
  3415.         {
  3416.         buf[0] = *p;
  3417.         send_to_server (buf, 1);
  3418.         }
  3419.     ++p;
  3420.     }
  3421.     send_to_server ("\012", 1);
  3422. }
  3423.  
  3424. static void send_modified PROTO ((char *, char *, Vers_TS *));
  3425.  
  3426. static void
  3427. send_modified (file, short_pathname, vers)
  3428.     char *file;
  3429.     char *short_pathname;
  3430.     Vers_TS *vers;
  3431. {
  3432.     /* File was modified, send it.  */
  3433.     struct stat sb;
  3434.     int fd;
  3435.     char *buf;
  3436.     char *mode_string;
  3437.     int bufsize;
  3438.     int bin;
  3439.  
  3440.     /* Don't think we can assume fstat exists.  */
  3441.     if (stat (file, &sb) < 0)
  3442.     error (1, errno, "reading %s", short_pathname);
  3443.  
  3444.     mode_string = mode_to_string (sb.st_mode);
  3445.  
  3446.     /* Beware: on systems using CRLF line termination conventions,
  3447.        the read and write functions will convert CRLF to LF, so the
  3448.        number of characters read is not the same as sb.st_size.  Text
  3449.        files should always be transmitted using the LF convention, so
  3450.        we don't want to disable this conversion.  */
  3451.     bufsize = sb.st_size;
  3452.     buf = xmalloc (bufsize);
  3453.  
  3454.     /* Is the file marked as containing binary data by the "-kb" flag?
  3455.        If so, make sure to open it in binary mode: */
  3456.  
  3457.     if (vers && vers->options)
  3458.       bin = !(strcmp (vers->options, "-kb"));
  3459.     else
  3460.       bin = 0;
  3461.  
  3462.     fd = open (file, O_RDONLY | (bin ? OPEN_BINARY : 0));
  3463.  
  3464.     if (fd < 0)
  3465.     error (1, errno, "reading %s", short_pathname);
  3466.  
  3467.     if (gzip_level && sb.st_size > 100)
  3468.     {
  3469.     int nread, newsize = 0, gzip_status;
  3470.     pid_t gzip_pid;
  3471.     char *bufp = buf;
  3472.     int readsize = 8192;
  3473. #ifdef LINES_CRLF_TERMINATED
  3474.     char tempfile[L_tmpnam];
  3475.     int converting;
  3476. #endif /* LINES_CRLF_TERMINATED */
  3477.  
  3478. #ifdef LINES_CRLF_TERMINATED
  3479.     /* Assume everything in a "cvs import" is text.  */
  3480.     if (vers == NULL)
  3481.         converting = 1;
  3482.     else
  3483.             /* Otherwise, we convert things unless they're binary. */
  3484.         converting = (! bin);
  3485.  
  3486.     if (converting)
  3487.     {
  3488.         /* gzip reads and writes files without munging CRLF
  3489.            sequences, as it should, but files should be
  3490.            transmitted in LF form.  Convert CRLF to LF before
  3491.            gzipping, on systems where this is necessary.
  3492.  
  3493.            If Windows NT supported fork, we could do this by
  3494.            pushing another filter on in front of gzip.  But it
  3495.            doesn't.  I'd have to write a trivial little program to
  3496.            do the conversion and have CVS spawn it off.  But
  3497.            little executables like that always get lost.
  3498.  
  3499.            Alternatively, this cruft could go away if we switched
  3500.            to a gzip library instead of a subprocess; then we
  3501.            could tell gzip to open the file with CRLF translation
  3502.            enabled.  */
  3503.         if (close (fd) < 0)
  3504.         error (0, errno, "warning: can't close %s", short_pathname);
  3505.  
  3506.         tmpnam (tempfile);
  3507.         convert_file (file, O_RDONLY,
  3508.               tempfile,
  3509.               O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY);
  3510.  
  3511.         /* This OPEN_BINARY doesn't make any difference, I think, because
  3512.            gzip will deal with the inherited handle as it pleases.  But I
  3513.            do remember something obscure in the manuals about propagating
  3514.            the translation mode to created processes via environment
  3515.            variables, ick.  */
  3516.         fd = open (tempfile, O_RDONLY | OPEN_BINARY);
  3517.         if (fd < 0)
  3518.         error (1, errno, "reading %s", short_pathname);
  3519.     }
  3520. #endif /* LINES_CRLF_TERMINATED */
  3521.  
  3522.     fd = filter_through_gzip (fd, 1, gzip_level, &gzip_pid);
  3523.  
  3524.     /* FIXME: is there any reason to go through all this realloc'ing
  3525.        when we could just be writing the data to the network as we read
  3526.        it from gzip?  */
  3527.     while (1)
  3528.     {
  3529.         if ((bufp - buf) + readsize >= bufsize)
  3530.         {
  3531.         /*
  3532.          * We need to expand the buffer if gzip ends up expanding
  3533.          * the file.
  3534.          */
  3535.         newsize = bufp - buf;
  3536.         while (newsize + readsize >= bufsize)
  3537.           bufsize *= 2;
  3538.         buf = xrealloc (buf, bufsize);
  3539.         bufp = buf + newsize;
  3540.         }
  3541.         nread = read (fd, bufp, readsize);
  3542.         if (nread < 0)
  3543.         error (1, errno, "reading from gzip pipe");
  3544.         else if (nread == 0)
  3545.         /* eof */
  3546.         break;
  3547.         bufp += nread;
  3548.     }
  3549.     newsize = bufp - buf;
  3550.     if (close (fd) < 0)
  3551.         error (0, errno, "warning: can't close %s", short_pathname);
  3552.  
  3553.     if (waitpid (gzip_pid, &gzip_status, 0) != gzip_pid)
  3554.         error (1, errno, "waiting for gzip proc %ld", (long) gzip_pid);
  3555.     else if (gzip_status != 0)
  3556.         error (1, errno, "gzip exited %d", gzip_status);
  3557.  
  3558. #if LINES_CRLF_TERMINATED
  3559.     if (converting)
  3560.     {
  3561.         if (unlink (tempfile) < 0)
  3562.         error (0, errno,
  3563.                "warning: can't remove temp file %s", tempfile);
  3564.     }
  3565. #endif /* LINES_CRLF_TERMINATED */
  3566.  
  3567.         {
  3568.           char tmp[80];
  3569.  
  3570.       send_to_server ("Modified ", 0);
  3571.       send_to_server (file, 0);
  3572.       send_to_server ("\012", 1);
  3573.       send_to_server (mode_string, 0);
  3574.       send_to_server ("\012z", 2);
  3575.       sprintf (tmp, "%lu\n", (unsigned long) newsize);
  3576.       send_to_server (tmp, 0);
  3577.  
  3578.           send_to_server (buf, newsize);
  3579.         }
  3580.     }
  3581.     else
  3582.     {
  3583.         int newsize;
  3584.  
  3585.         {
  3586.         char *bufp = buf;
  3587.         int len;
  3588.  
  3589.         /* FIXME: This is gross.  It assumes that we might read
  3590.            less than st_size bytes (true on NT), but not more.
  3591.            Instead of this we should just be reading a block of
  3592.            data (e.g. 8192 bytes), writing it to the network, and
  3593.            so on until EOF.  */
  3594.         while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
  3595.             bufp += len;
  3596.  
  3597.         if (len < 0)
  3598.             error (1, errno, "reading %s", short_pathname);
  3599.  
  3600.         newsize = bufp - buf;
  3601.     }
  3602.     if (close (fd) < 0)
  3603.         error (0, errno, "warning: can't close %s", short_pathname);
  3604.  
  3605.         {
  3606.           char tmp[80];
  3607.  
  3608.       send_to_server ("Modified ", 0);
  3609.       send_to_server (file, 0);
  3610.       send_to_server ("\012", 1);
  3611.       send_to_server (mode_string, 0);
  3612.       send_to_server ("\012", 1);
  3613.           sprintf (tmp, "%lu\012", (unsigned long) newsize);
  3614.           send_to_server (tmp, 0);
  3615.         }
  3616.  
  3617.     /*
  3618.      * Note that this only ends with a newline if the file ended with
  3619.      * one.
  3620.      */
  3621.     if (newsize > 0)
  3622.           send_to_server (buf, newsize);
  3623.     }
  3624.     free (buf);
  3625.     free (mode_string);
  3626. }
  3627.  
  3628. static int send_fileproc PROTO ((struct file_info *finfo));
  3629.  
  3630. /* Deal with one file.  */
  3631. static int
  3632. send_fileproc (finfo)
  3633.     struct file_info *finfo;
  3634. {
  3635.     Vers_TS *vers;
  3636.  
  3637.     send_a_repository ("", finfo->repository, finfo->update_dir);
  3638.  
  3639.     vers = Version_TS ((char *)NULL, (char *)NULL, (char *)NULL,
  3640.                (char *)NULL,
  3641.                finfo->file, 0, 0, finfo->entries, (RCSNode *)NULL);
  3642.  
  3643.     if (vers->vn_user != NULL)
  3644.     {
  3645.       char *tmp;
  3646.  
  3647.       tmp = xmalloc (strlen (finfo->file) + strlen (vers->vn_user)
  3648.              + strlen (vers->options) + 200);
  3649.       sprintf (tmp, "Entry /%s/%s/%s%s/%s/", 
  3650.                finfo->file, vers->vn_user,
  3651.                vers->ts_conflict == NULL ? "" : "+",
  3652.                (vers->ts_conflict == NULL ? ""
  3653.                 : (vers->ts_user != NULL &&
  3654.                    strcmp (vers->ts_conflict, vers->ts_user) == 0
  3655.                    ? "="
  3656.                    : "modified")),
  3657.                vers->options);
  3658.  
  3659.     /* The Entries request.  */
  3660.     /* Not sure about whether this deals with -k and stuff right.  */
  3661.     send_to_server (tmp, 0);
  3662.         free (tmp);
  3663.     if (vers->entdata != NULL && vers->entdata->tag)
  3664.     {
  3665.         send_to_server ("T", 0);
  3666.         send_to_server (vers->entdata->tag, 0);
  3667.     }
  3668.     else if (vers->entdata != NULL && vers->entdata->date)
  3669.           {
  3670.         send_to_server ("D", 0);
  3671.         send_to_server (vers->entdata->date, 0);
  3672.           }
  3673.     send_to_server ("\012", 1);
  3674.     }
  3675.  
  3676.     if (vers->ts_user == NULL)
  3677.     {
  3678.     /*
  3679.      * Do we want to print "file was lost" like normal CVS?
  3680.      * Would it always be appropriate?
  3681.      */
  3682.     /* File no longer exists.  */
  3683.     if (!use_unchanged)
  3684.     {
  3685.         /* if the server is old, use the old request... */
  3686.         send_to_server ("Lost ", 0);
  3687.         send_to_server (finfo->file, 0);
  3688.         send_to_server ("\012", 1);
  3689.         /*
  3690.          * Otherwise, don't do anything for missing files,
  3691.          * they just happen.
  3692.          */
  3693.     }
  3694.     }
  3695.     else if (vers->ts_rcs == NULL
  3696.          || strcmp (vers->ts_user, vers->ts_rcs) != 0)
  3697.     {
  3698.     send_modified (finfo->file, finfo->fullname, vers);
  3699.     }
  3700.     else
  3701.     {
  3702.     /* Only use this request if the server supports it... */
  3703.     if (use_unchanged)
  3704.           {
  3705.         send_to_server ("Unchanged ", 0);
  3706.         send_to_server (finfo->file, 0);
  3707.         send_to_server ("\012", 1);
  3708.           }
  3709.     }
  3710.  
  3711.     /* if this directory has an ignore list, add this file to it */
  3712.     if (ignlist)
  3713.     {
  3714.     Node *p;
  3715.  
  3716.     p = getnode ();
  3717.     p->type = FILES;
  3718.     p->key = xstrdup (finfo->file);
  3719.     (void) addnode (ignlist, p);
  3720.     }
  3721.  
  3722.     freevers_ts (&vers);
  3723.     return 0;
  3724. }
  3725.  
  3726. static void send_ignproc PROTO ((char *, char *));
  3727.  
  3728. static void
  3729. send_ignproc (file, dir)
  3730.     char *file;
  3731.     char *dir;
  3732. {
  3733.     if (ign_inhibit_server || !supported_request ("Questionable"))
  3734.     {
  3735.     if (dir[0] != '\0')
  3736.         (void) printf ("? %s/%s\n", dir, file);
  3737.     else
  3738.         (void) printf ("? %s\n", file);
  3739.     }
  3740.     else
  3741.     {
  3742.     send_to_server ("Questionable ", 0);
  3743.     send_to_server (file, 0);
  3744.     send_to_server ("\012", 1);
  3745.     }
  3746. }
  3747.  
  3748. static int send_filesdoneproc PROTO ((int, char *, char *));
  3749.  
  3750. static int
  3751. send_filesdoneproc (err, repository, update_dir)
  3752.     int err;
  3753.     char *repository;
  3754.     char *update_dir;
  3755. {
  3756.     /* if this directory has an ignore list, process it then free it */
  3757.     if (ignlist)
  3758.     {
  3759.     ignore_files (ignlist, update_dir, send_ignproc);
  3760.     dellist (&ignlist);
  3761.     }
  3762.  
  3763.     return (err);
  3764. }
  3765.  
  3766. static Dtype send_dirent_proc PROTO ((char *, char *, char *));
  3767.  
  3768. /*
  3769.  * send_dirent_proc () is called back by the recursion processor before a
  3770.  * sub-directory is processed for update.
  3771.  * A return code of 0 indicates the directory should be
  3772.  * processed by the recursion code.  A return of non-zero indicates the
  3773.  * recursion code should skip this directory.
  3774.  *
  3775.  */
  3776. static Dtype
  3777. send_dirent_proc (dir, repository, update_dir)
  3778.     char *dir;
  3779.     char *repository;
  3780.     char *update_dir;
  3781. {
  3782.     int dir_exists;
  3783.     char *cvsadm_repos_name;
  3784.  
  3785.     /*
  3786.      * If the directory does not exist yet (e.g. "cvs update -d
  3787.      * foo"), no need to send any files from it.
  3788.      */
  3789.     dir_exists = isdir (dir);
  3790.  
  3791.     if (ignore_directory (update_dir))
  3792.     {
  3793.     /* print the warm fuzzy message */
  3794.     if (!quiet)
  3795.         error (0, 0, "Ignoring %s", update_dir);
  3796.         return (R_SKIP_ALL);
  3797.     }
  3798.  
  3799.     /* initialize the ignore list for this directory */
  3800.     ignlist = getlist ();
  3801.  
  3802.     /*
  3803.      * If there is an empty directory (e.g. we are doing `cvs add' on a
  3804.      * newly-created directory), the server still needs to know about it.
  3805.      */
  3806.  
  3807.     cvsadm_repos_name = xmalloc (strlen (dir) + sizeof (CVSADM_REP) + 80);
  3808.     sprintf (cvsadm_repos_name, "%s/%s", dir, CVSADM_REP);
  3809.     if (dir_exists && isreadable (cvsadm_repos_name))
  3810.     {
  3811.     /*
  3812.      * Get the repository from a CVS/Repository file whenever possible.
  3813.      * The repository variable is wrong if the names in the local
  3814.      * directory don't match the names in the repository.
  3815.      */
  3816.     char *repos = Name_Repository (dir, update_dir);
  3817.     send_a_repository (dir, repos, update_dir);
  3818.     free (repos);
  3819.     }
  3820.     else
  3821.     send_a_repository (dir, repository, update_dir);
  3822.     free (cvsadm_repos_name);
  3823.  
  3824.     return (dir_exists ? R_PROCESS : R_SKIP_ALL);
  3825. }
  3826.  
  3827. /*
  3828.  * Send each option in a string to the server, one by one.
  3829.  * This assumes that the options are single characters.  For
  3830.  * more complex parsing, do it yourself.
  3831.  */
  3832.  
  3833. void
  3834. send_option_string (string)
  3835.     char *string;
  3836. {
  3837.     char *p;
  3838.     char it[3];
  3839.  
  3840.     for (p = string; p[0]; p++) {
  3841.     if (p[0] == ' ')
  3842.         continue;
  3843.     if (p[0] == '-')
  3844.         continue;
  3845.     it[0] = '-';
  3846.     it[1] = p[0];
  3847.     it[2] = '\0';
  3848.     send_arg (it);
  3849.     }
  3850. }
  3851.  
  3852.  
  3853. /* Send the names of all the argument files to the server.  */
  3854.  
  3855. void
  3856. send_file_names (argc, argv, flags)
  3857.     int argc;
  3858.     char **argv;
  3859.     unsigned int flags;
  3860. {
  3861.     int i;
  3862.     char *p;
  3863.     char *q;
  3864.     int level;
  3865.     int max_level;
  3866.  
  3867.     /* The fact that we do this here as well as start_recursion is a bit 
  3868.        of a performance hit.  Perhaps worth cleaning up someday.  */
  3869.     if (flags & SEND_EXPAND_WILD)
  3870.     expand_wild (argc, argv, &argc, &argv);
  3871.  
  3872.     /* Send Max-dotdot if needed.  */
  3873.     max_level = 0;
  3874.     for (i = 0; i < argc; ++i)
  3875.     {
  3876.     p = argv[i];
  3877.     level = 0;
  3878.     do
  3879.     {
  3880.         q = strchr (p, '/');
  3881.         if (q != NULL)
  3882.         ++q;
  3883.         if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || p[2] == '/'))
  3884.         {
  3885.         --level;
  3886.         if (-level > max_level)
  3887.             max_level = -level;
  3888.         }
  3889.         else if (p[0] == '.' && (p[1] == '\0' || p[1] == '/'))
  3890.         ;
  3891.         else
  3892.         ++level;
  3893.         p = q;
  3894.     } while (p != NULL);
  3895.     }
  3896.     if (max_level > 0)
  3897.     {
  3898.     if (supported_request ("Max-dotdot"))
  3899.     {
  3900.             char buf[10];
  3901.             sprintf (buf, "%d", max_level);
  3902.  
  3903.         send_to_server ("Max-dotdot ", 0);
  3904.         send_to_server (buf, 0);
  3905.         send_to_server ("\012", 1);
  3906.     }
  3907.     else
  3908.         /*
  3909.          * "leading .." is not strictly correct, as this also includes
  3910.          * cases like "foo/../..".  But trying to explain that in the
  3911.          * error message would probably just confuse users.
  3912.          */
  3913.         error (1, 0,
  3914.            "leading .. not supported by old (pre-Max-dotdot) servers");
  3915.     }
  3916.  
  3917.     for (i = 0; i < argc; ++i)
  3918.     {
  3919.     char buf[1];
  3920.     char *p = argv[i];
  3921.  
  3922.     send_to_server ("Argument ", 0);
  3923.  
  3924.     while (*p)
  3925.     {
  3926.         if (*p == '\n')
  3927.         {
  3928.         send_to_server ("\012Argumentx ", 0);
  3929.         }
  3930.         else if (ISDIRSEP (*p))
  3931.         {
  3932.         buf[0] = '/';
  3933.         send_to_server (buf, 1);
  3934.         }
  3935.         else
  3936.         {
  3937.         buf[0] = *p;
  3938.         send_to_server (buf, 1);
  3939.         }
  3940.         ++p;
  3941.     }
  3942.     send_to_server ("\012", 1);
  3943.     }
  3944.  
  3945.     if (flags & SEND_EXPAND_WILD)
  3946.     {
  3947.     int i;
  3948.     for (i = 0; i < argc; ++i)
  3949.         free (argv[i]);
  3950.     free (argv);
  3951.     }
  3952. }
  3953.  
  3954.  
  3955. /*
  3956.  * Send Repository, Modified and Entry.  argc and argv contain only
  3957.  * the files to operate on (or empty for everything), not options.
  3958.  * local is nonzero if we should not recurse (-l option).  Also sends
  3959.  * Argument lines for argc and argv, so should be called after options
  3960.  * are sent.
  3961.  */
  3962. void
  3963. send_files (argc, argv, local, aflag)
  3964.     int argc;
  3965.     char **argv;
  3966.     int local;
  3967.     int aflag;
  3968. {
  3969.     int err;
  3970.  
  3971.     /*
  3972.      * aflag controls whether the tag/date is copied into the vers_ts.
  3973.      * But we don't actually use it, so I don't think it matters what we pass
  3974.      * for aflag here.
  3975.      */
  3976.     err = start_recursion
  3977.     (send_fileproc, send_filesdoneproc,
  3978.      send_dirent_proc, (DIRLEAVEPROC)NULL,
  3979.      argc, argv, local, W_LOCAL, aflag, 0, (char *)NULL, 0, 0);
  3980.     if (err)
  3981.     exit (EXIT_FAILURE);
  3982.     if (toplevel_repos == NULL)
  3983.     /*
  3984.      * This happens if we are not processing any files,
  3985.      * or for checkouts in directories without any existing stuff
  3986.      * checked out.  The following assignment is correct for the
  3987.      * latter case; I don't think toplevel_repos matters for the
  3988.      * former.
  3989.      */
  3990.     toplevel_repos = xstrdup (server_cvsroot);
  3991.     send_repository ("", toplevel_repos, ".");
  3992. }
  3993.  
  3994. void
  3995. client_import_setup (repository)
  3996.     char *repository;
  3997. {
  3998.     if (toplevel_repos == NULL)        /* should always be true */
  3999.         send_a_repository ("", repository, "");
  4000. }
  4001.  
  4002. /*
  4003.  * Process the argument import file.
  4004.  */
  4005. int
  4006. client_process_import_file (message, vfile, vtag, targc, targv, repository)
  4007.     char *message;
  4008.     char *vfile;
  4009.     char *vtag;
  4010.     int targc;
  4011.     char *targv[];
  4012.     char *repository;
  4013. {
  4014.     char *short_pathname;
  4015.     int first_time;
  4016.  
  4017.     /* FIXME: I think this is always false now that we call
  4018.        client_import_setup at the start.  */
  4019.  
  4020.     first_time = toplevel_repos == NULL;
  4021.  
  4022.     if (first_time)
  4023.     send_a_repository ("", repository, "");
  4024.  
  4025.     if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)) != 0)
  4026.     error (1, 0,
  4027.            "internal error: pathname `%s' doesn't specify file in `%s'",
  4028.            repository, toplevel_repos);
  4029.     short_pathname = repository + strlen (toplevel_repos) + 1;
  4030.  
  4031.     if (!first_time)
  4032.     {
  4033.     send_a_repository ("", repository, short_pathname);
  4034.     }
  4035.     send_modified (vfile, short_pathname, NULL);
  4036.     return 0;
  4037. }
  4038.  
  4039. void
  4040. client_import_done ()
  4041. {
  4042.     if (toplevel_repos == NULL)
  4043.     /*
  4044.      * This happens if we are not processing any files,
  4045.      * or for checkouts in directories without any existing stuff
  4046.      * checked out.  The following assignment is correct for the
  4047.      * latter case; I don't think toplevel_repos matters for the
  4048.      * former.
  4049.      */
  4050.         /* FIXME: "can't happen" now that we call client_import_setup
  4051.        at the beginning.  */
  4052.     toplevel_repos = xstrdup (server_cvsroot);
  4053.     send_repository ("", toplevel_repos, ".");
  4054. }
  4055.  
  4056. static void
  4057. notified_a_file (data, ent_list, short_pathname, filename)
  4058.     char *data;
  4059.     List *ent_list;
  4060.     char *short_pathname;
  4061.     char *filename;
  4062. {
  4063.     FILE *fp;
  4064.     FILE *newf;
  4065.     size_t line_len = 8192;
  4066.     char *line = xmalloc (line_len);
  4067.     char *cp;
  4068.     int nread;
  4069.     int nwritten;
  4070.     char *p;
  4071.  
  4072.     fp = open_file (CVSADM_NOTIFY, "r");
  4073.     if (getline (&line, &line_len, fp) < 0)
  4074.     {
  4075.     error (0, errno, "cannot read %s", CVSADM_NOTIFY);
  4076.     goto error_exit;
  4077.     }
  4078.     cp = strchr (line, '\t');
  4079.     if (cp == NULL)
  4080.     {
  4081.     error (0, 0, "malformed %s file", CVSADM_NOTIFY);
  4082.     goto error_exit;
  4083.     }
  4084.     *cp = '\0';
  4085.     if (strcmp (filename, line + 1) != 0)
  4086.     {
  4087.     error (0, 0, "protocol error: notified %s, expected %s", filename,
  4088.            line + 1);
  4089.     }
  4090.  
  4091.     if (getline (&line, &line_len, fp) < 0)
  4092.     {
  4093.     if (feof (fp))
  4094.     {
  4095.         if (fclose (fp) < 0)
  4096.         error (0, errno, "cannot close %s", CVSADM_NOTIFY);
  4097.         if (unlink (CVSADM_NOTIFY) < 0)
  4098.         error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
  4099.         return;
  4100.     }
  4101.     else
  4102.     {
  4103.         error (0, errno, "cannot read %s", CVSADM_NOTIFY);
  4104.         goto error_exit;
  4105.     }
  4106.     }
  4107.     newf = open_file (CVSADM_NOTIFYTMP, "w");
  4108.     if (fputs (line, newf) < 0)
  4109.     {
  4110.     error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
  4111.     goto error2;
  4112.     }
  4113.     while ((nread = fread (line, 1, line_len, fp)) > 0)
  4114.     {
  4115.     p = line;
  4116.     while ((nwritten = fwrite (p, 1, nread, newf)) > 0)
  4117.     {
  4118.         nread -= nwritten;
  4119.         p += nwritten;
  4120.     }
  4121.     if (ferror (newf))
  4122.     {
  4123.         error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
  4124.         goto error2;
  4125.     }
  4126.     }
  4127.     if (ferror (fp))
  4128.     {
  4129.     error (0, errno, "cannot read %s", CVSADM_NOTIFY);
  4130.     goto error2;
  4131.     }
  4132.     if (fclose (newf) < 0)
  4133.     {
  4134.     error (0, errno, "cannot close %s", CVSADM_NOTIFYTMP);
  4135.     goto error_exit;
  4136.     }
  4137.     if (fclose (fp) < 0)
  4138.     {
  4139.     error (0, errno, "cannot close %s", CVSADM_NOTIFY);
  4140.     return;
  4141.     }
  4142.  
  4143.     {
  4144.         /* In this case, we want rename_file() to ignore noexec. */
  4145.         int saved_noexec = noexec;
  4146.         noexec = 0;
  4147.         rename_file (CVSADM_NOTIFYTMP, CVSADM_NOTIFY);
  4148.         noexec = saved_noexec;
  4149.     }
  4150.  
  4151.     return;
  4152.   error2:
  4153.     (void) fclose (newf);
  4154.   error_exit:
  4155.     (void) fclose (fp);
  4156. }
  4157.  
  4158. static void
  4159. handle_notified (args, len)
  4160.     char *args;
  4161.     int len;
  4162. {
  4163.     call_in_directory (args, notified_a_file, NULL);
  4164. }
  4165.  
  4166. void
  4167. client_notify (repository, update_dir, filename, notif_type, val)
  4168.     char *repository;
  4169.     char *update_dir;
  4170.     char *filename;
  4171.     int notif_type;
  4172.     char *val;
  4173. {
  4174.     char buf[2];
  4175.  
  4176.     send_a_repository ("", repository, update_dir);
  4177.     send_to_server ("Notify ", 0);
  4178.     send_to_server (filename, 0);
  4179.     send_to_server ("\012", 1);
  4180.     buf[0] = notif_type;
  4181.     buf[1] = '\0';
  4182.     send_to_server (buf, 1);
  4183.     send_to_server ("\t", 1);
  4184.     send_to_server (val, 0);
  4185. }
  4186.  
  4187. /*
  4188.  * Send an option with an argument, dealing correctly with newlines in
  4189.  * the argument.  If ARG is NULL, forget the whole thing.
  4190.  */
  4191. void
  4192. option_with_arg (option, arg)
  4193.     char *option;
  4194.     char *arg;
  4195. {
  4196.     if (arg == NULL)
  4197.     return;
  4198.  
  4199.     send_to_server ("Argument ", 0);
  4200.     send_to_server (option, 0);
  4201.     send_to_server ("\012", 1);
  4202.  
  4203.     send_arg (arg);
  4204. }
  4205.  
  4206. /*
  4207.  * Send a date to the server.  This will passed a string which is the
  4208.  * result of Make_Date, and looks like YY.MM.DD.HH.MM.SS, where all
  4209.  * the letters are single digits.  The time will be GMT.  getdate on
  4210.  * the server can't parse that, so we turn it back into something
  4211.  * which it can parse.
  4212.  */
  4213.  
  4214. void
  4215. client_senddate (date)
  4216.     const char *date;
  4217. {
  4218.     int year, month, day, hour, minute, second;
  4219.     char buf[100];
  4220.  
  4221.     if (sscanf (date, DATEFORM, &year, &month, &day, &hour, &minute, &second)
  4222.     != 6)
  4223.     {
  4224.         error (1, 0, "diff_client_senddate: sscanf failed on date");
  4225.     }
  4226.  
  4227. #ifndef HAVE_RCS5
  4228.     /* We need to fix the timezone in this case; see Make_Date.  */
  4229.     abort ();
  4230. #endif /* HAVE_RCS5 */
  4231.  
  4232.     sprintf (buf, "%d/%d/%d %d:%d:%d GMT", month, day, year,
  4233.          hour, minute, second);
  4234.     option_with_arg ("-D", buf);
  4235. }
  4236.  
  4237. int
  4238. client_commit (argc, argv)
  4239.     int argc;
  4240.     char **argv;
  4241. {
  4242.     parse_cvsroot ();
  4243.  
  4244.     return commit (argc, argv);
  4245. }
  4246.  
  4247. int
  4248. client_update (argc, argv)
  4249.     int argc;
  4250.     char **argv;
  4251. {
  4252.     parse_cvsroot ();
  4253.  
  4254.     return update (argc, argv);
  4255. }
  4256.  
  4257. int
  4258. client_checkout (argc, argv)
  4259.     int argc;
  4260.     char **argv;
  4261. {
  4262.     parse_cvsroot ();
  4263.     
  4264.     return checkout (argc, argv);
  4265. }
  4266.  
  4267. int
  4268. client_diff (argc, argv)
  4269.     int argc;
  4270.     char **argv;
  4271. {
  4272.     parse_cvsroot ();
  4273.  
  4274.     return diff (argc, argv);    /* Call real code */
  4275. }
  4276.  
  4277. int
  4278. client_status (argc, argv)
  4279.     int argc;
  4280.     char **argv;
  4281. {
  4282.     parse_cvsroot ();
  4283.     return status (argc, argv);
  4284. }
  4285.  
  4286. int
  4287. client_log (argc, argv)
  4288.     int argc;
  4289.     char **argv;
  4290. {
  4291.     
  4292.     parse_cvsroot ();
  4293.     
  4294.     return cvslog (argc, argv);    /* Call real code */
  4295. }
  4296.  
  4297. int
  4298. client_add (argc, argv)
  4299.     int argc;
  4300.     char **argv;
  4301. {
  4302.     
  4303.     parse_cvsroot ();
  4304.     
  4305.     return add (argc, argv);    /* Call real code */
  4306. }
  4307.  
  4308. int
  4309. client_remove (argc, argv)
  4310.     int argc;
  4311.     char **argv;
  4312. {
  4313.     
  4314.     parse_cvsroot ();
  4315.     
  4316.     return cvsremove (argc, argv);    /* Call real code */
  4317. }
  4318.  
  4319. int
  4320. client_rdiff (argc, argv)
  4321.     int argc;
  4322.     char **argv;
  4323. {
  4324.     
  4325.     parse_cvsroot ();
  4326.     
  4327.     return patch (argc, argv);    /* Call real code */
  4328. }
  4329.  
  4330. int
  4331. client_tag (argc, argv)
  4332.     int argc;
  4333.     char **argv;
  4334. {
  4335.     
  4336.     parse_cvsroot ();
  4337.     
  4338.     return tag (argc, argv);    /* Call real code */
  4339. }
  4340.  
  4341. int
  4342. client_rtag (argc, argv)
  4343.     int argc;
  4344.     char **argv;
  4345. {
  4346.     
  4347.     parse_cvsroot ();
  4348.     
  4349.     return rtag (argc, argv);    /* Call real code */
  4350. }
  4351.  
  4352. int
  4353. client_import (argc, argv)
  4354.     int argc;
  4355.     char **argv;
  4356. {
  4357.     
  4358.     parse_cvsroot ();
  4359.     
  4360.     return import (argc, argv);    /* Call real code */
  4361. }
  4362.  
  4363. int
  4364. client_admin (argc, argv)
  4365.     int argc;
  4366.     char **argv;
  4367. {
  4368.     
  4369.     parse_cvsroot ();
  4370.     
  4371.     return admin (argc, argv);    /* Call real code */
  4372. }
  4373.  
  4374. int
  4375. client_export (argc, argv)
  4376.     int argc;
  4377.     char **argv;
  4378. {
  4379.     
  4380.     parse_cvsroot ();
  4381.     
  4382.     return checkout (argc, argv);    /* Call real code */
  4383. }
  4384.  
  4385. int
  4386. client_history (argc, argv)
  4387.     int argc;
  4388.     char **argv;
  4389. {
  4390.     
  4391.     parse_cvsroot ();
  4392.     
  4393.     return history (argc, argv);    /* Call real code */
  4394. }
  4395.  
  4396. int
  4397. client_release (argc, argv)
  4398.     int argc;
  4399.     char **argv;
  4400. {
  4401.     
  4402.     parse_cvsroot ();
  4403.     
  4404.     return release (argc, argv);    /* Call real code */
  4405. }
  4406.  
  4407. int
  4408. client_watch (argc, argv)
  4409.     int argc;
  4410.     char **argv;
  4411. {
  4412.     
  4413.     parse_cvsroot ();
  4414.     
  4415.     return watch (argc, argv);    /* Call real code */
  4416. }
  4417.  
  4418. int
  4419. client_watchers (argc, argv)
  4420.     int argc;
  4421.     char **argv;
  4422. {
  4423.     
  4424.     parse_cvsroot ();
  4425.     
  4426.     return watchers (argc, argv);    /* Call real code */
  4427. }
  4428.  
  4429. int
  4430. client_editors (argc, argv)
  4431.     int argc;
  4432.     char **argv;
  4433. {
  4434.     
  4435.     parse_cvsroot ();
  4436.     
  4437.     return editors (argc, argv);    /* Call real code */
  4438. }
  4439.  
  4440. int
  4441. client_edit (argc, argv)
  4442.     int argc;
  4443.     char **argv;
  4444. {
  4445.     
  4446.     parse_cvsroot ();
  4447.     
  4448.     return edit (argc, argv);    /* Call real code */
  4449. }
  4450.  
  4451. int
  4452. client_unedit (argc, argv)
  4453.     int argc;
  4454.     char **argv;
  4455. {
  4456.     
  4457.     parse_cvsroot ();
  4458.     
  4459.     return unedit (argc, argv);    /* Call real code */
  4460. }
  4461.  
  4462. void
  4463. send_init_command ()
  4464. {
  4465.     /* This is here because we need the server_cvsroot variable.  */
  4466.     send_to_server ("init ", 0);
  4467.     send_to_server (server_cvsroot, 0);
  4468.     send_to_server ("\012", 0);
  4469. }
  4470.  
  4471. int
  4472. client_init (argc, argv)
  4473.     int argc;
  4474.     char **argv;
  4475. {
  4476.     parse_cvsroot ();
  4477.  
  4478.     return init (argc, argv);    /* Call real code */
  4479. }
  4480.  
  4481. int
  4482. client_annotate (argc, argv)
  4483.     int argc;
  4484.     char **argv;
  4485. {
  4486.     parse_cvsroot ();
  4487.  
  4488.     return annotate (argc, argv);    /* Call real code */
  4489. }
  4490. #endif /* CLIENT_SUPPORT */
  4491.